使用 java 8 流处理空属性并使用 lambda 表达式进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31284282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dealing with a null attribute using java 8 streams and sorting using lambda expressions
提问by Manu Joy
Let's consider a Parent
class which contains only one Integer
attribute. I created 6 objects of parent class and values of attribute are 100, 20, 300, 400, 500, null
.
让我们考虑一个Parent
只包含一个Integer
属性的类。我创建了 6 个父类对象,属性值是100, 20, 300, 400, 500, null
.
Now I added all the objects to a list(Name of list is list). Then I want to get the objects whose attribute value is greater than 100
. I used Java 8 streams for this purpose.
现在我将所有对象添加到列表中(列表名称为列表)。然后我想获取属性值大于 的对象100
。为此,我使用了 Java 8 流。
Predicate<Entity> predicate = e -> e.getParentId() < 100;
result = list.stream().filter(predicate).collect(Collectors.toList());
I also want to sort the list in descending order. I used the following code for this purpose.
我还想按降序对列表进行排序。为此,我使用了以下代码。
Comparator<Entity> comp = (d1,d2) -> d2.getId().compareTo(d1.getId());
list.sort(comp);
In both cases I get a NullPointerException
.
在这两种情况下,我都会得到一个NullPointerException
.
How to handle this?
如何处理?
回答by Brian Goetz
All of the answers here revolve around "throw out the bad elements, those that have a null getParentId()
." That may be the answer, if they are indeed bad. But there's another alternative: Comparators.nullsFirst
(or last.) This allows you to compare things treating a null value as being less than (or greater than) all non-null values, so you don't have to throw the elements with a null parentId away.
这里的所有答案都围绕着“扔掉坏元素,那些有 null 的元素getParentId()
”。如果它们确实很糟糕,那可能就是答案。但是还有另一种选择:(Comparators.nullsFirst
或最后一个。)这允许您比较将空值视为小于(或大于)所有非空值的事物,因此您不必将具有空 parentId 的元素扔掉.
Comparator<Entity> cmp = nullsLast(comparing(Entity::getParentId));
List<Entity> list = list.stream().sorted(cmp).collect(toList());
You can do a similar thing for filtering; define your predicate as:
您可以为过滤做类似的事情;将谓词定义为:
Predicate<Entity> predicate = e -> e.getParentId() != null
&& e.getParentId() < 100;
回答by joetde
Looks like you are looking for something like:
看起来你正在寻找类似的东西:
list.sort(Comparator.comparing(Entity::getParent,
Comparator.nullsLast(Integer::compareTo)));
All the elements with parent null will be put at the end and the rest will be sorted by their parent.
所有父元素为 null 的元素将放在最后,其余元素将按其父元素排序。
回答by Dominik Sandjaja
Try pre-filtering for non-null parentId
values only:
尝试parentId
仅对非空值进行预过滤:
result = list.stream().filter(e -> e.getParentId() != null).filter(predicate).collect(Collectors.toList());
[edit]
Just saw, that the attribute (e.parentId
) seems the one being null
. In that case, the second thing, the sorting, breaks. You are sorting the original list, not the filtered one. Try result.sort(comp)
, then you should avoid the NPE.
[编辑] 刚刚看到,属性 ( e.parentId
) 似乎是null
. 在这种情况下,第二件事,排序,中断了。您正在对原始列表进行排序,而不是过滤后的列表。尝试result.sort(comp)
,那么您应该避免使用 NPE。
回答by Eran
You can do it all in one Stream pipeline :
您可以在一个 Stream 管道中完成所有操作:
List<Entity> result =
list.stream()
.filter(e -> e.getParentId()!=null) // it's not clear if the null
// is the Entity object itself
// (in which case it should be e!=null)
// or just the ParentId member
.filter(predicate)
.sorted(comp)
.collect(Collectors.toList());
BTW, according to the text of your question, the original predicate should be :
顺便说一句,根据你的问题的文字,原来的谓词应该是:
Predicate<Entity> predicate = e -> e.getParentId() > 100; // not < 100
回答by Fritz Duchardt
Harness the power of a method referenceto make the code even more compact:
利用方法引用的强大功能使代码更加紧凑:
List<Entity> result =
list.stream()
.filter(Objects::nonNull)
.filter(predicate)
.sorted(comp)
.collect(Collectors.toList());
回答by Konstantin Yovkov
You can do:
你可以做:
Predicate<Entity> predicate = e -> e.getParentId() < 100;
Predicate<Entity> nonNull = e -> e != null;
result = list.stream().filter(nonNull)
.filter(predicate)
.collect(Collectors.toList());
Of course, you could combinethe predicates into one, but I introduced a second one for better readability. Also, you're free to change the nonNull
predicate to check either the whole entity, or just the id
attribute (or even both). Just play a bit with it. :)
当然,您可以将谓词合二为一,但为了更好的可读性,我引入了第二个谓词。此外,您可以自由更改nonNull
谓词以检查整个实体,或仅检查id
属性(甚至两者)。只是玩一下。:)