Возврат списка из list.forEach с Java Streaming API - PullRequest
1 голос
/ 28 марта 2019

У меня есть POJO:

class MyObject {
   private Double a;
   private String b;

   //constructor, getter + setter
}

Некоторая функция создает список этого POJO.Некоторые значения для a могут быть нулевыми, поэтому я хочу заменить их на 0.0.На данный момент я делаю это так.

public List<MyObject> fetchMyObjects(Predicate predicate) {

     List<MyObject> list = getMyListsOfTheDatabase(predicate);

     list
       .forEach(myObject -> {
           if (myObject.getA() == null) {
               myObject.setA(0.0);
           }
     });

    return list;
}

Есть ли способ интегрировать forEach в возврат?Что-то вроде

 return list
         .stream()
         .someStatement();

Дело не в том, если это лучшее место для преобразования нулей в ноль, а скорее в вопрос, чтобы лучше понять API потоковой передачи.

Ответы [ 6 ]

2 голосов
/ 28 марта 2019

Хотя другие были рады ответить на ваш вопрос в его нынешнем виде, позвольте мне сделать шаг назад и дать вам ответ, который вы не просили (но, возможно, ответ, который вы хотите): Вы не хотитесделай это.Операция потока не должна иметь побочных эффектов.То, что вы просите, - это именно потоковая операция, которая имеет побочный эффект изменения исходных объектов, поступающих в поток.Такой плохой стиль кода и может запутать тех, кто читает ваш код после вас.

Код, который у вас уже есть, решает вашу проблему гораздо лучше, чем любой объединенный потоковый конвейер.

То, что вы, возможно, захотитеЕсли у вас есть возможность изменить ваш POJO, это либо конструктор, который устанавливает a в 0, если null было получено из базы данных, либо метод, который делает это, который вы можете вызвать из list.forEach:

    list.forEach(MyObject::setAToZeroIfNull);

Дело не в том, если это лучшее место для преобразования нулей в ноль, а скорее в вопросы, чтобы лучше понять API потоковой передачи.

Это справедливо.В любом случае, я оставлю этот ответ для всех, кто заскочил.

2 голосов
/ 28 марта 2019

Использование функции peek

Возвращает поток, состоящий из элементов этого потока, дополнительно выполняя предоставленное действие для каждого элемента, поскольку элементы потребляются из результирующегопоток.

public List<MyObject> fetchMyObjects(Predicate predicate) {
    return getMyListsOfTheDatabase(predicate)
            .stream()
            .peek(it -> if(it.getA() == null) it.setA(0.0))
            .collect(Collectors.toList());
}
1 голос
/ 28 марта 2019

На самом деле вы должны использовать List::replaceAll:

list.replaceAll(x -> {
    if(x.getA() == null) x.setA(0.0D);
    return x;
})
1 голос
/ 28 марта 2019

Вы не можете вернуть один и тот же экземпляр List с помощью одного оператора, но вы можете вернуть новый List экземпляр, содержащий такие же (возможно, измененные) элементы:

return list.stream()
           .map(myObject -> {
               if (myObject.getA() == null) {
                   myObject.setA(0.0);
               }
               return myObject;
           })
           .collect(Collectors.toList());
0 голосов
/ 28 марта 2019

Следующее будет хорошо:

list.stream()
    .filter(obj -> obj.getA() == null)
    .forEach(obj -> obj.setA(0.0));
return list;

Однако в вашем случае более подходящим может быть только возврат потока (зависит):

public Stream<MyObject> fetchMyObjects(Predicate predicate) {
     return getMyListsOfTheDatabase(predicate);
}

public Stream<MyObject> streamMyObjects(List<MyObject> list) {
     return list.stream()
         .peek(obj -> {
             if (obj.getA() == null) {
                 obj.setA(0.0);
             }
         });
}

Лично я никогда не использовал peek, но здесь он исправляет значения.

Об условных обозначениях кода, которые являются более строковыми в сообществе java:

  • Отступ: Java взял 4 в отличие от C ++ 3 как более отдельные методы, и ожидалось меньше отступов. Спорно, но в порядке.
  • Для параметров универсального типа часто используется одна заглавная буква, например T, C, S.
  • Для лямбда-параметров короткие имена, часто одна буква, поэтому я использовал obj.
0 голосов
/ 28 марта 2019

forEach не имеет возвращаемого значения, поэтому вы можете искать map

return list
    .stream()
    .map(e -> {
        if (e.getA() == null) e.setA(0d);
        return e;
    })
    .whateverElse()...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...