Легкий способ исправить это объявление типа в вызове метода foo
:
Foo.foo(value -> true).booleanValue();
Редактировать: Я не могу найти конкретную документацию о почему это необходимо, почти так же, как и все остальные. Я подозревал, что это может быть из-за примитивных типов, но это было неправильно. Независимо от того, этот синтаксис вызывается с использованием целевого типа . Также Тип цели в Lambdas . Однако причины не ускользают от меня, я не могу найти документацию в любом месте о том, почему этот конкретный случай использования необходим.
Редактировать 2: Я нашел этот вопрос:
Вывод общего типа не работает с цепочкой методов?
Похоже, это потому, что вы цепляете методы здесь. Согласно комментариям JSR, указанным в принятом ответе, это было преднамеренное упущение функциональности, потому что у компилятора нет способа передать полученную информацию общего типа между цепными вызовами метода в обоих направлениях. В результате весь тип стираемого по времени до вызова booleanValue
. Добавление целевого типа удаляет это поведение, предоставляя ограничение вручную, а не позволяя компилятору принять решение, используя правила, изложенные в JLS §18 , что, похоже, не упоминает об этом вообще. Это единственная информация, которую я мог бы придумать. Если кто-нибудь найдет что-нибудь лучше, я бы хотел его увидеть.
Я думаю, что второй лучше. 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"]
Для лучшей производительности и для вставки замещающих значений в правильное положение используйте 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]
Я бы сделал это очень похоже на ваш первый путь:
if (attributes.remove("*")) {
attributes.addAll(additionalValues);
}
Вам не нужен отдельный remove
и contains
вызов для правильно реализованной коллекции :
[
Collection.remove(Object)
] Удаляет один экземпляр указанного элемента из этой коллекции, если он присутствует (дополнительная операция). Более формально удаляет элемент e такой, что (o == null? E == null: o.equals (e)), если эта коллекция содержит один или несколько таких элементов. Возвращает true, если эта коллекция содержала указанный элемент (или, что то же самое, если эта коллекция была изменена в результате вызова).