我相信OP正在使用比较器将input分割成等价类,并且所需结果是根据该比较器最大等价类的成员列表。
不幸的是,使用int值作为示例问题是一个可怕的例子。 所有相等的int值都是可replace的,所以不存在保留等价值的顺序的概念。 也许一个更好的例子是使用string长度,其中期望的结果是从input中返回所有具有最长长度的string列表。
我不知道有什么办法做到这一点,而不至less在部分结果中存储部分结果。
给定一个input集合,说
List list = ... ;
它足够简单,可以通过两遍来完成,第一个获得最长的长度,第二个过滤具有该长度的string:
int longest = list.stream() .mapToInt(String::length) .max() .orElse(-1); List result = list.stream() .filter(s -> s.length() == longest) .collect(toList());
如果input是一个不能被遍历多次的stream,则可以使用一个收集器仅仅一次计算结果。 编写这样一个收集器并不困难,但是由于有几个案例需要处理,所以有点繁琐。 给定一个比较器,产生这样一个收集器的帮助函数如下:
static Collector> maxList(Comparator super T> comp) { return Collector.of( ArrayList::new, (list, t) -> { int c; if (list.isEmpty() || (c = comp.compare(t, list.get(0))) == 0) { list.add(t); } else if (c > 0) { list.clear(); list.add(t); } }, (list1, list2) -> { if (list1.isEmpty()) { return list2; } if (list2.isEmpty()) { return list1; } int r = comp.compare(list1.get(0), list2.get(0)); if (r < 0) { return list2; } else if (r > 0) { return list1; } else { list1.addAll(list2); return list1; } }); }
这将中间结果存储在ArrayList 。 不变的是,任何这样的列表中的所有元素在比较器方面是等同的。 当添加元素时,如果它小于列表中的元素,则忽略它; 如果它是平等的,它被添加; 如果更大,列表将被清空,并添加新的元素。 合并也不是太困难:具有更大元素的列表被返回,但是如果它们的元素相等,则列表被追加。
给定一个inputstream,这很容易使用:
Stream input = ... ; List result = input.collect(maxList(comparing(String::length)));