Как эффективно сгладить каждый элемент коллекции?
Каков наиболее эффективный способ опускания каждого элемента списка или набора?
Моя идея для списка:
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 (или List), можно ли это сделать без создания дополнительного временного набора?
Что-то вроде этого было бы хорошо:
Set<String> strings = new HashSet<String>();
strings.apply(
function (element)
{ this.replace(element, element.toLowerCase();) }
);
Спасибо,
Ответы
Ответ 1
Это похоже на довольно чистое решение для списков. Это должно позволить использовать конкретную реализацию List для реализации, которая оптимальна как для обхода списка - в линейном времени, так и для замены строки - в постоянное время.
public static void replace(List<String> strings)
{
ListIterator<String> iterator = strings.listIterator();
while (iterator.hasNext())
{
iterator.set(iterator.next().toLowerCase());
}
}
Это лучшее, что я могу придумать для наборов. Как говорили другие, операция не может быть выполнена на месте в наборе по ряду причин. Строку нижнего регистра, возможно, необходимо разместить в другом месте в наборе, чем строка, которую она заменяет. Более того, строчная строка не может быть добавлена к множеству вообще, если она идентична другой строчной строчке, которая уже добавлена (например, "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));
}
Ответ 2
Еще одно решение, но с Java 8 и выше:
List<String> result = strings.stream()
.map(String::toLowerCase)
.collect(Collectors.toList());
Ответ 3
Вы можете сделать это с помощью Google Collections:
Collection<String> lowerCaseStrings = Collections2.transform(strings,
new Function<String, String>() {
public String apply(String str) {
return str.toLowerCase();
}
}
);
Ответ 4
Ну, нет настоящего элегантного решения из-за двух фактов:
-
String
в Java неизменяемы
- Java не дает вам реальной приятной функции
map(f, list)
, как у вас есть на функциональных языках.
Асимптотически говоря, вы не можете получить лучшее время работы, чем ваш текущий метод. Вам нужно будет создать новую строку с помощью toLowerCase()
, и вам нужно будет перебирать ее по списку и генерировать каждую новую строчную строку, заменяя ее на существующую.
Ответ 5
Попробуйте CollectionUtils # transform в коллекциях Commons для решения на месте или Collections2 # transform в Guava, если вам нужен живой просмотр.
Ответ 6
Это, вероятно, быстрее:
for(int i=0,l=strings.size();i<l;++i)
{
strings.set(i, strings.get(i).toLowerCase());
}
Ответ 7
Я не считаю, что можно сделать манипуляцию на месте (без создания другой коллекции), если вы измените строки как Set. Это связано с тем, что вы можете выполнять только итерацию по набору с помощью итератора или для каждого цикла и не можете вставлять новые объекты во время выполнения этого действия (он выдает исключение)
Ответ 8
Ссылаясь на метод ListIterator в принятом решении (Matthew T. Staebler). Как лучше использовать ListIterator, чем метод здесь?
public static Set<String> replace(List<String> strings) {
Set<String> set = new HashSet<>();
for (String s: strings)
set.add(s.toLowerCase());
return set;
}
Ответ 9
Я искал похожие вещи, но застрял, потому что мой ArrayList объект не был объявлен как GENERIC, и он был доступен как raw List тип объекта откуда-то. Я просто получал объект ArrayList "_products". Итак, то, что я сделал, упоминается ниже, и это отлично сработало для меня:
List<String> dbProducts = _products;
for(int i = 0; i<dbProducts.size(); i++) {
dbProducts.add(dbProducts.get(i).toLowerCase());
}
То есть, я сначала взял мои доступные _products и сделал объект GENERIC (поскольку у меня были только строки), я применил toLowerCase() на элементах списка, которые ранее не работали из-за не общего объекта ArrayList.
И метод toLowerCase(), который мы используем здесь, имеет класс String.
Строка java.lang.String.toLowerCase()
не класса ArrayList или Object.
Пожалуйста, исправьте, если неправильно. Новичок в JAVA ищет руководство.:)
Ответ 10
Используя параллельный поток JAVA 8, он становится быстрее
List<String> output= new ArrayList<>();
List<String> input= new ArrayList<>();
input.add("A");
input.add("B");
input.add("C");
input.add("D");
input.stream().parallel().map((item) -> item.toLowerCase())
.collect(Collectors.toCollection(() -> output));
Ответ 11
Если у вас все в порядке с изменением списка ввода, вот еще один способ добиться этого.
strings.replaceAll(String::toLowerCase)