Лямбда-выражения в Java с использованием объекта-предиката в фильтре

#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. Итак, я мог бы написать предикат<Целое число>, чтобы быть более точным. Пожалуйста, поправьте меня, если я ошибаюсь.