Подтвердить что ты не робот

Как эффективно сгладить каждый элемент коллекции?

Каков наиболее эффективный способ опускания каждого элемента списка или набора?

Моя идея для списка:

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();) } 
);

Спасибо,

4b9b3361

Ответ 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(), и вам нужно будет перебирать ее по списку и генерировать каждую новую строчную строку, заменяя ее на существующую.

Ответ 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)