#java #lambda
#java #лямбда
Вопрос:
Это простой код, выбирающий случайное подмножество целых чисел из списка целых чисел с использованием лямбда-выражений. Функция выполняет итерацию по списку, и для каждого элемента вызывается случайное логическое значение. На основе этого выбирается или отбрасывается элемент.
public static List<Integer> getRandomSubsetUsingLambda(List<Integer> list) {
List<Integer> randomSubset = new ArrayList<>();
Random random = new Random();
Predicate<Object> flipCoin = o -> {
return random.nextBoolean();
};
randomSubset = list.stream().filter(flipCoin).collect(Collectors.toList());
return randomSubset;
}
Я понимаю, что фильтр, основанный на логическом значении ta, выбирает целые числа. Но я не понимал, как это происходит. Означает ли это, что всякий раз, когда вызывается FlipCoin, возвращается логическое значение?
Комментарии:
1. Добавьте
System.out.println("flipCoing called for " o);
непосредственно передreturn random.nextBoolean();
в свое лямбда-выражение, затем снова запустите свой поток. Вы увидите.
Ответ №1:
filter() вызовет FlipCoin, передав в качестве параметра повторенное значение из потока. Затем FlipCoin сгенерирует случайное логическое значение (игнорируя значение его параметра), и если false, повторенное значение из потока будет отброшено.
т.е. для каждого элемента в потоке генерируется случайное логическое значение и используется для решения (случайным образом), принят элемент или отброшен.
Ответ №2:
Давайте выберем практический пример с List
, содержащий три элемента [1, 2, 3]
1
list.stream()
.filter(flipCoin) // random.nextBoolean() returns true so 1 goes through
.collect(Collectors.toList()); // 1 is waiting to be added to the list
2
list.stream()
.filter(flipCoin) // random.nextBoolean() returns false and 2 is blocked
.collect(Collectors.toList());
3
list.stream()
.filter(flipCoin) // random.nextBoolean() returns true
.collect(Collectors.toList()); // 3 is the last element of your stream so the list is created
Новое List
содержит [1, 3]
По сути, при каждом filter(flipCoin)
вызове выполняется следующий блочный код для каждого element
прохождения через него (здесь Integer
-s)
public boolean test(Object o) {
return random.nextBoolean();
}
По сути, ваш поток эквивалентен следующему блоку кода
List<Integer> newList = new ArrayList<>();
for (Integer i : list) {
boolean shouldBeAddedToNewList = random.nextBoolean();
if (shouldBeAddedToNewList) {
newList.add(i);
}
}
Комментарии:
1. Понял. Спасибо. Одно небольшое сомнение, я думаю, что в лямбда-выражении FlipCoin ‘o’ имеет тип integer. Итак, я мог бы написать предикат<Целое число>, чтобы быть более точным. Пожалуйста, поправьте меня, если я ошибаюсь.