Лучший способ заменить элемент коллекции несколькими элементами в Java

Легкий способ исправить это объявление типа в вызове метода foo:

Foo.foo(value -> true).booleanValue();

Редактировать: Я не могу найти конкретную документацию о почему это необходимо, почти так же, как и все остальные. Я подозревал, что это может быть из-за примитивных типов, но это было неправильно. Независимо от того, этот синтаксис вызывается с использованием целевого типа . Также Тип цели в Lambdas . Однако причины не ускользают от меня, я не могу найти документацию в любом месте о том, почему этот конкретный случай использования необходим.

Редактировать 2: Я нашел этот вопрос:

Вывод общего типа не работает с цепочкой методов?

Похоже, это потому, что вы цепляете методы здесь. Согласно комментариям JSR, указанным в принятом ответе, это было преднамеренное упущение функциональности, потому что у компилятора нет способа передать полученную информацию общего типа между цепными вызовами метода в обоих направлениях. В результате весь тип стираемого по времени до вызова booleanValue. Добавление целевого типа удаляет это поведение, предоставляя ограничение вручную, а не позволяя компилятору принять решение, используя правила, изложенные в JLS §18 , что, похоже, не упоминает об этом вообще. Это единственная информация, которую я мог бы придумать. Если кто-нибудь найдет что-нибудь лучше, я бы хотел его увидеть.

0
задан Sean 13 July 2018 в 21:38
поделиться

3 ответа

Я думаю, что второй лучше. Arrays.asList("X","Y","Z") извлекают ArrayList, т. е. массив. Это нехорошо заменить значения в нем.

В общем случае, если вы хотите изменить colletion (например, заменить * на X, Y и Z), do создайте новую коллекцию в некотором роде.

Посмотрите на LinkedList, если вы хотите сами изменить коллекцию.

Использование потоков:

public static List<String> replace(Collection<String> attributes, String value, Collection<String> additionalValues) {
    return attributes.stream()
                     .map(val -> value.equals(val) ? additionalValues.stream() : Stream.of(val))
                     .flatMap(Function.identity())
                     .collect(Collectors.toList());
}

Не использовать потоки

public static List<String> replace(Collection<String> attributes, String value, Collection<String> additionalValues) {
    List<String> res = new LinkedList<>();

    for (String attribute : attributes) {
        if (value.equals(attribute))
            res.addAll(additionalValues);
        else
            res.add(attribute);
    }

    return res;
}

Демонстрация:

List<String> attributes = Arrays.asList("A", "B", "*", "C");
List<String> res = replace(attributes, "*", Arrays.asList("X", "Y", "Z"));  // ["A", "B", "X", "Y", "Z", "C"]
0
ответ дан oleg.cherednik 17 August 2018 в 12:07
поделиться
  • 1
    ДополнительныеValues ​​может быть любой коллекцией, именно так мне удалось определить список там. В фактическом коде это коллекция, проходящая через этот метод, поэтому она уже определена в другом месте – Sean 13 July 2018 в 21:48
  • 2
    Я вижу, что вы говорите для создания нового списка. Хорошо, спасибо! – Sean 13 July 2018 в 22:11

Для лучшей производительности и для вставки замещающих значений в правильное положение используйте indexOf(o) , remove(index) и addAll(index, c) :

Демо

List<String> attributes = new ArrayList<>(Arrays.asList("A", "B", "*", "C"));
Collection<String> additionalValues = Arrays.asList("X","Y","Z");

int idx = attributes.indexOf("*");
if (idx != -1) {
    attributes.remove(idx);
    attributes.addAll(idx, additionalValues);
}

System.out.println(attributes);

Выход

[A, B, X, Y, Z, C]

Если заказ не введите значение возврата remove(o) :

if (attributes.remove("*"))
    attributes.addAll(additionalValues);

Выход

[A, B, C, X, Y, Z]
0
ответ дан Andreas 17 August 2018 в 12:07
поделиться

Я бы сделал это очень похоже на ваш первый путь:

if (attributes.remove("*")) {
    attributes.addAll(additionalValues);
}

Вам не нужен отдельный remove и contains вызов для правильно реализованной коллекции :

[Collection.remove(Object)] Удаляет один экземпляр указанного элемента из этой коллекции, если он присутствует (дополнительная операция). Более формально удаляет элемент e такой, что (o == null? E == null: o.equals (e)), если эта коллекция содержит один или несколько таких элементов. Возвращает true, если эта коллекция содержала указанный элемент (или, что то же самое, если эта коллекция была изменена в результате вызова).

2
ответ дан Andy Turner 17 August 2018 в 12:07
поделиться
  • 1
    wow, полностью забыл .remove () возвратил логическое значение. Хороший звонок. – Sean 13 July 2018 в 22:11
Другие вопросы по тегам:

Похожие вопросы: