Java8:如何比较集合中的所有元素

Java8:如何比较集合中的所有元素,java,java-8,java-stream,Java,Java 8,Java Stream,这可能是一个已经问过的问题,但我没有找到我需要的答案 我有一套像这样的东西 public class MyObject { private LocalDate dateBeginning; private LocalDate dateEnd; public boolean overlap(MyObject otherDate) { /*code to check overlapping*/ } } 我需要检查集合是否包含相互重叠的to元素。在“OldJava”中,我将

这可能是一个已经问过的问题,但我没有找到我需要的答案

我有一套像这样的东西

public class MyObject {
    private LocalDate dateBeginning;
    private LocalDate dateEnd;

    public boolean overlap(MyObject otherDate) { /*code to check overlapping*/ }
}
我需要检查集合是否包含相互重叠的to元素。在“OldJava”中,我将对集合进行两次检查,检查存在的所有组合,然后在找到它时中断或返回

在Java8中,如何使用streams和lambda实现这一点

我已经尝试过
reduce()
filter()
了,但它们似乎都不起作用

.filter((obj1, obj2) -> { if (obj1.overlap(obj2)) return true;}) //doesn't work

正如您在问题中所说,一个可能的解决方案是在集合上循环两次,并确定是否存在重叠。因此,我们需要确定的是,对于集合中的任何元素,我们是否可以找到与之不同并重叠的任何其他元素

使用流API,您可以实现以下功能:

boolean overlap = set.stream()
    .anyMatch(
        o1 -> set.stream().anyMatch(o2 -> o1 != o2 && o1.overlap(o2))
    );
将确定流的任何元素是否满足给定条件。因此,上面的代码询问是否有一个
o1
,这样就有一个
o2
不同于
o1
(我们可以在这里安全地使用
!=
,因为两个对象都来自同一个集合)并与其重叠


请注意,这是一个O(n²)实现:该集合被遍历两次。这在单个迭代中是可能的:在每个迭代中,间隔的并集
[datestart,dateEnd]
;如果在任何时候,当前间隔和累计并集之间的交集是非无效的,则我们知道发生了重叠。

使用
compareTo
覆盖的思想实现。如果需要精确地获取重叠范围或其编号,请使用此选项

public class Range implements Comparable<Range> {
    private LocalDate startDate;
    private LocalDate endDate;

    public Range(LocalDate startDate, LocalDate endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
    }

    @Override
    public int compareTo(Range range) {
        if (range.endDate.compareTo(endDate) >= 0 && range.startDate.compareTo(endDate) >= 0) return 1;
        if (range.endDate.compareTo(startDate) <= 0 && range.startDate.compareTo(startDate) <= 0) return -1;
        return 0;
    }
}
公共类范围实现可比较{
私有LocalDate开始日期;
私有LocalDate-endDate;
公共范围(LocalDate开始日期、LocalDate结束日期){
this.startDate=startDate;
this.endDate=endDate;
}
@凌驾
公共整数比较(范围){
如果(range.endDate.compareTo(endDate)>=0&&range.startDate.compareTo(endDate)>=0)返回1;
如果(range.endDate.compareTo(startDate),我也可以建议在这种情况下使用类和
parallelStream
来获得性能。结合这一点,我们可以得到:

Set ranges=new HashSet();
范围添加(范围介于(2016年5月1日的LocalDate)和(2016年5月5日的LocalDate)之间);
范围添加(范围介于(2016年5月3日的LocalDate)和(2016年5月7日的LocalDate)之间);
布尔重叠=范围.parallelStream().anyMatch(
o1->ranges.parallelStream()
.anyMatch(o2->o1!=o2&&o1.isOverlappedBy(o2))
);
System.out.println(“重叠=”+重叠);

不是你问题的答案,不过@Eran我认为这可能会有帮助@Eran我认为OP需要一组与集合中任何其他元素重叠的所有元素。是的@Eran我想要一个布尔值。但是要得到一个包含重叠元素的列表也可以,因为你正在处理
集合
s,因此顺序不重要d如果您没有以任何方式修改
Set
,您可能会发现使用
parallelStream()是有利的
,如果你的
集合很大,这可能会加快速度。请看下面的答案:这是一个非常好的答案!首先,代码可以工作,其次,在一次迭代中完成这项工作的可能性是一个非常好的点。有没有一种方法可以用流来替代此方法?对于所有尝试此方法的人,请注意,你不能使用相同的stream tweep:这意味着您需要调用
set.stream()
两次,正如答案中所写的那样。如果您直接在流上工作,它将不工作。这将不工作:
stream stream=set.stream();boolean overlap=stream.anyMatch(o1->stream.anyMatch(o2->o1!=o2&&o1.overlap(o2)))是的,但是你必须重新设计你的类,首先创建一个
DateInterval
类,这个类将有一个
union
和一个
intersect
方法。是的,如上所述,你不能重用流,它们是一次性的。我要注意,正如我在OP上提到的,
parallelStream()
如果所涉及的集合较大,则在这里可能是有利的。使用
Comparable
-界面来实现这一点不是一个很好的主意。问题1:这并不是范围的“自然”排序-对于该类用户来说,什么是“更大”并不明显范围意味着-更长的一个或更晚的一个。2:此比较定义的顺序不是总顺序(例如,可能存在范围a、B和C,使a>B、a=C和B=C)。
LocalDate May1 = LocalDate.of(2016, 5, 1);
LocalDate May3 = LocalDate.of(2016, 5, 3);
LocalDate May5 = LocalDate.of(2016, 5, 5);
LocalDate May7 = LocalDate.of(2016, 5, 7);
LocalDate May9 = LocalDate.of(2016, 5, 9);

Set<Range> ranges = new HashSet<>();

ranges.add(new Range(May1, May5));
ranges.add(new Range(May3, May7));
ranges.add(new Range(May7, May9));

Set filteredRanges = ranges.stream().collect(Collectors.toCollection(TreeSet::new));
long totalOverlaps = ranges.size() - filteredRanges.size();
System.out.println(totalOverlaps + " overlapping range(s)"); 
Set<Range> ranges = new HashSet<>();
ranges.add(Range.between(LocalDate.of(2016, 5, 1), LocalDate.of(2016, 5, 5)));
ranges.add(Range.between(LocalDate.of(2016, 5, 3), LocalDate.of(2016, 5, 7)));

boolean overlap = ranges.parallelStream().anyMatch(
                o1 -> ranges.parallelStream()
                        .anyMatch(o2 -> o1 != o2 && o1.isOverlappedBy(o2))
);

System.out.println("overlap = " + overlap);