Что самым эффективным путем является к нижнему регистру каждый элемент Списка или Набора?
Моя идея для Списка:
final List<String> strings = new ArrayList<String>();
strings.add("HELLO");
strings.add("WORLD");
for(int i=0,l=strings.size();i<l;++i)
{
strings.add(strings.remove(0).toLowerCase());
}
Существует ли лучший, более быстрый путь? Как этот пример был бы похож для Набора? Как в настоящее время нет никакого метода для применения операции к каждому элементу Набора (или Список), это может быть сделано, не создавая дополнительный временный Набор?
Что-то вроде этого было бы хорошо:
Set<String> strings = new HashSet<String>();
strings.apply(
function (element)
{ this.replace(element, element.toLowerCase();) }
);
Спасибо,
Это кажется довольно чистым решением для списков. Он должен позволять использовать конкретную реализацию List для обеспечения реализации, оптимальной как для обхода списка - за линейное время - так и для замены строки - за постоянное время.
public static void replace(List<String> strings)
{
ListIterator<String> iterator = strings.listIterator();
while (iterator.hasNext())
{
iterator.set(iterator.next().toLowerCase());
}
}
Это лучшее, что я могу придумать для наборов. Как уже говорили другие, операция не может быть выполнена на месте в наборе по ряду причин. Строку нижнего регистра, возможно, потребуется поместить в другое место в наборе, чем строка, которую она заменяет. Более того, строчная строка может вообще не быть добавлена к набору, если она идентична другой строчной строке, которая уже была добавлена (например, «HELLO» и «Hello» оба дадут «hello», что приведет к добавляется в набор только один раз).
public static void replace(Set<String> strings)
{
String[] stringsArray = strings.toArray(new String[0]);
for (int i=0; i<stringsArray.length; ++i)
{
stringsArray[i] = stringsArray[i].toLowerCase();
}
strings.clear();
strings.addAll(Arrays.asList(stringsArray));
}
Попробуйте преобразовать CollectionUtils # в Commons Collections для решения на месте или Collections2 # преобразовать в Guava если вам нужен живой просмотр.
Я не верю, что можно выполнять манипуляции на месте (без создания другой Коллекции), если вы измените строки на Набор. Это связано с тем, что вы можете перебирать Set только с помощью итератора или для каждого цикла и не можете вставлять новые объекты при этом (это вызывает исключение)
Это можно сделать с помощью Коллекций Google:
Collection<String> lowerCaseStrings = Collections2.transform(strings,
new Function<String, String>() {
public String apply(String str) {
return str.toLowerCase();
}
}
);
Это, вероятно, быстрее:
for(int i=0,l=strings.size();i<l;++i)
{
strings.set(i, strings.get(i).toLowerCase());
}
Что ж, настоящего элегантного решения не существует из-за двух фактов:
Строки
в Java неизменяемы функция map (f, list)
, как и в функциональных языках. Говоря асимптотически, вы не можете получить лучшее время выполнения, чем ваш текущий метод. Вам нужно будет создать новую строку, используя toLowerCase ()
, и вам нужно будет самостоятельно перебирать список и генерировать каждую новую строку в нижнем регистре, заменяя ее существующей.