使用新的Java8API流和lambdas表达式检查两个集合

使用新的Java8API流和lambdas表达式检查两个集合,java,lambda,java-8,Java,Lambda,Java 8,我有两个集合,它们都由相同类型的对象组成,这种类型的对象有一个字段,在本例中是“codeType” 我需要检查第二个集合中的所有“代码类型”是否与第一个集合中的相同,是否没有添加其他代码类型。我可以迭代两个集合来获取id,然后检查它们。 但是当我们使用Java8时,我想使用streams和lambdas(因为我正在学习它) 到目前为止,我所做的就是: Boolean collectionEquals = CollectionUtils.isNotEmpty(oldOrderPositions)

我有两个集合,它们都由相同类型的对象组成,这种类型的对象有一个字段,在本例中是“codeType”

我需要检查第二个集合中的所有“代码类型”是否与第一个集合中的相同,是否没有添加其他代码类型。我可以迭代两个集合来获取id,然后检查它们。 但是当我们使用Java8时,我想使用streams和lambdas(因为我正在学习它)

到目前为止,我所做的就是:

Boolean collectionEquals = CollectionUtils.isNotEmpty(oldOrderPositions)
    ? oldOrderPositions.stream()
                       .mapToLong(oldPosition -> 
                                     oldPosition.getCodeType().getId())
                       .allMatch(newOrderPositions.stream()
                                                  .mapToLong(newPosition -> 
                                                                 newPosition.getCodeType().getId()))
   : false;
基本上,我得到两个集合,我遍历它们以获得Id,并检查所有Id是否匹配。然而,我得到一个编译错误,它说“LongStream中的allMatch(java.util.fuction.Predicate)不能应用于(java.util.stream.LongStream)”

你能帮帮我吗?我不知道我做错了什么,也不知道我错了什么


感谢您抽出时间

一个
谓词
必须接受一个
组件并返回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));
}
公共无效测试(){
集合oldOrderPositions=new ArrayList();
集合newOrderPositions=newArrayList();
布尔collectionEquals=oldOrderPositions
.stream()
.allMatch(代码->newOrderPositions.contains(代码));
}
在这里,我们对old进行流式处理,并坚持它们都匹配谓词
newOrderPositions.contains
——也就是说,每一个old都在new中


请注意,我只使用了
集合

就大大简化了您的机制。其他两种解决方案要么不检查doublons,要么不检查订单

使用此解决方案,您可以检查是否存在所有ID,如果存在Doublon,则无论其位置如何:

return Arrays.equals(
    oldOrderPositions.stream()
      .mapToLong(p -> p.getCodeType().getId())
      .sorted()
      .toArray(),
    newOrderPositions.stream()
      .mapToLong(p -> p.getCodeType().getId())
      .sorted()
      .toArray()
  );
当然,您可以重构它,让方法进行转换,但由于我不知道
oldOrderPositions
newOrderPositions
是否属于同一类型,所以我自己没有这样做。如果是,请执行以下操作:

static long[] normalize(Collection<OrderPosition> orderPositions) {
  return orderPositions.stream()
      .mapToLong(p -> p.getCodeType().getId())
      .sorted()
      .toArray();
}
...
return Arrays.equals(
  normalize(oldOrderPositions),
  normalize(newOrderPositions)
);
static long[]规范化(集合顺序位置){
returnorderpositions.stream()返回
.mapToLong(p->p.getCodeType().getId())
.已排序()
.toArray();
}
...
返回数组.equals(
正常化(oldOrderPositions),
正常化(新订单位置)
);

哦,是的,你写了你想用流来做这件事。我不得不说,仅仅因为你有一把锤子,你不会用它把所有的东西都装在墙上。有时你需要一把螺丝刀。这就是这样一个解决方案,使用适当的工具解决适当的问题。流对于问题的一部分(转换)是有用的,但是为了进行比较,我建议您使用其他一些好的工具,因此使用
Arrays.equals()

我觉得您正在重新发明轮子。。请像这样使用Google guava项目中的一个,java.lang.Iterable)@FirstX为什么要使用库来处理这个简单的问题?@dit因为这不是一个“简单的问题”。这是一个非常重要的比较操作,而streams并不是很适合这样做。使用一个库做你想做的事情(这是正确的)比创建一个DIY错误的实用工具方法更可取。事实上,这不是一个简单的问题,但这个问题并不需要大量的知识,而且可以用最少的努力找到解决方案。为此使用库可能会很麻烦。如果Guava已经是一个依赖项,我会使用它,但如果不是,我会编写自己的版本。另外,为了回答问题本身,您尝试应用
谓词
,而不是
长谓词
。这就是你做错的,在问题的“汇编”部分。这个答案否定了问题中所有特别复杂的部分,即1。转变,2。需要在类型和3之间切换。类似列表的比较,而不是类似集合的比较。@OlivierGrégoire——尽管如此——它处理的是一个实际问题,即为什么在LongStream中说“allMatch(java.util.fuction.Predicate)的错误不能应用于(java.util.stream.LongStream)”,而答案是使用谓词,这就是我的观点2:这个人特别要求比较long,而你回答比较字符串(或任何你想要的对象),在这种情况下,我们特别需要一个
谓词
。这个答案没有用,你说的完全有道理,谢谢。不管怎样,我在页面顶部看到了你推荐的番石榴(我以前从未使用过),以防它已经是项目中的一个依赖项,我只是检查了一下,它确实是。你的解决方案很优雅,我很喜欢,但是你会推荐使用番石榴而不是这个解决方案,还是相反?这是个人选择的问题。与Guava一起使用解决方案的优点是,您没有责任测试此代码,并且您确信它能按预期工作。如果你使用番石榴,最好使用两个
Multiset
并比较它们,而不是
Iterables.elementEquals()
(这就是Kocko的答案)。另一方面,这里为您提供了一个完整的解决方案,用于您的具体用例,这是您的决定。缺点是为了确保精确匹配,您必须对多头进行排序。如果您的列表不是很大,那么这是一个很好的解决方案。如果没有,用番石榴。