2015-03-13 25 views
1

我有两个集合,它们都由相同类型的对象组成,这种类型的对象有一个字段,在本例中为'codeType'。使用新的Java 8 API流和lambda表达式检查两个集合

我需要检查在第二个集合中,所有'codeTypes'与第一个集合中的相同,没有额外添加。我可以这样做,只是迭代两个集合以获取id,然后检查它们。 但是当我们使用的是Java 8,我想用流和lambda表达式(因为我学习吧)

这是迄今为止我所做的一切它做的事:

Boolean collectionEquals = CollectionUtils.isNotEmpty(oldOrderPositions) 
    ? oldOrderPositions.stream() 
         .mapToLong(oldPosition -> 
            oldPosition.getCodeType().getId()) 
         .allMatch(newOrderPositions.stream() 
                .mapToLong(newPosition -> 
                   newPosition.getCodeType().getId())) 
    : false; 

基本上我获取两个集合,我遍历它们以获取Id,然后检查所有id的匹配。然而,我收到一个编译错误,说“LongMream中的allMatch(java.util.fuction.Predicate)不能应用于(java.util.stream.LongStream)”

你能帮我吗?我不知道我在做什么错,或者我在误会。

谢谢您的时间

+1

我觉得你正在重塑车轮..请使用这样的Google guava项目之一http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/ collect/Iterables.html#elementsEqual(java.lang.Iterable,java.lang.Iterable) – rakpan 2015-03-13 10:55:14

+0

@FirstX为什么他应该为这个简单的问题使用一个库? – dit 2015-03-13 11:01:27

+0

@dit因为它不是**“简单的问题”。这是一个不平凡的比较操作,并且流并不适合这种情况。使用一个库来完成你想要的(和正确的)是最好的创建一个DIY窃听效用方法 – Vogel612 2015-03-13 11:13:12

回答

3

其他解决方案或者不检查双重或顺序。

有了这个解决方案,您可以检查所有的ID都存在,如果事件有杜布隆不管他们的立场:

return Arrays.equals(
    oldOrderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray(), 
    newOrderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray() 
); 

当然,你可以重构这个有方法做了变换,但因为我不知道oldOrderPositionsnewOrderPositions是否属于同一类型,所以我没有自己做。如果是这样,只要这样做:

static long[] normalize(Collection<OrderPosition> orderPositions) { 
    return orderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray(); 
} 
... 
return Arrays.equals(
    normalize(oldOrderPositions), 
    normalize(newOrderPositions) 
); 

哦,是的,你写,你想使用的流来做到这一点。我不得不说,只因为你有一把锤子,你不会把所有东西都放在墙上。有时你需要一把螺丝刀。所以这是一个解决方案,使用合适的工具来解决相应的问题。流对于问题的一部分(转换)很有用,但为了进行比较,我建议您采用其他一些好的工具,因此可以使用Arrays.equals()

+0

完全了解你在说什么,谢谢。无论如何,我在页面的顶部看到,如果已经是项目的依赖项,我推荐番石榴(我从来没有用过),我只是检查过它。你的解决方案是优雅的,我喜欢它,但你会推荐使用番石榴然后通过这个解决方案,或相反? – fgonzalez 2015-03-13 12:28:00

+1

这是个人选择的问题。与Guava一起使用解决方案的好处是,您无需测试此代码的责任,并且确信它可以按预期工作。如果你使用番石榴,你最好使用两个'Multiset '并比较那些,而不是'Iterables.elementEquals()'(然后成为Kocko的答案)。另一方面,在这里你有一个完整的解决方案提供给你的确切用例,这是你的电话。缺点是要确保完全匹配,您必须对多头进行排序。如果你的清单不是很大,这是一个不错的解决方案。如果没有,请使用番石榴。 – 2015-03-13 12:41:51

-1

一个Predicate必须采取Stream分量和返回true或false。你可能打算这样做:

public void test() { 
    Collection<String> oldOrderPositions = new ArrayList<String>(); 
    Collection<String> newOrderPositions = new ArrayList<String>(); 
    Boolean collectionEquals = oldOrderPositions 
      .stream() 
      .allMatch(code -> newOrderPositions.contains(code)); 
} 

在这里,我们将流和孩子坚持他们所有的谓语newOrderPositions.contains匹配 - 即孩子的每一个也是新的。

请注意,我通过使用Collection<String>大大简化了您的机制。

+1

这个答案否定了问题中所有特别复杂的部分,即1.变换,2.需要在类型之间切换,3.列表类比较,而不是集合类比较。 – 2015-03-13 11:28:30

+0

@OlivierGrégoire - 尽管如此,它处理的是真正的问题,它是为什么在LongStream中的错误说“allMatch(java.util.fuction.Predicate)不能应用于(java.util.stream.LongStream)”*答案是*使用Predicate *。 – OldCurmudgeon 2015-03-13 11:30:52

+1

不,这是我的观点2:人特意要求比较多头和你回答比较字符串(或任何你想要的对象),在这种情况下,我们特别需要一个' Predicate'。这个答案使用这个事实无处。 – 2015-03-13 11:34:09