当前位置: 首页 > 知识库问答 >
问题:

如何强制max返回Java流中的所有最大值?

戚逸清
2023-03-14

我在Java 8 lambdas和streams上测试max函数,似乎在执行max的情况下,即使有多个对象与0相比,它也会返回绑定候选项中的任意元素,而无需进一步考虑。

对于这样的最大期望行为,是否有一个明显的技巧或函数,以便返回所有的最大值?我在API中没有看到任何东西,但我确信它一定存在比手动比较更好的东西。

例如:

// myComparator is an IntegerComparator
Stream.of(1, 3, 5, 3, 2, 3, 5)
    .max(myComparator)
    .forEach(System.out::println);
// Would print 5, 5 in any order.

共有1个答案

祁烨
2023-03-14

我认为OP正在使用比较器将输入划分为等价类,期望的结果是根据比较器得出的最大等价类成员列表。

不幸的是,使用int值作为示例问题是一个糟糕的例子。所有相等的int值都是可替换的,因此没有保留等价值顺序的概念。也许一个更好的例子是使用字符串长度,其中期望的结果是从输入中返回一个字符串列表,这些字符串在该输入中都具有最长的长度。

我不知道有什么方法可以做到这一点,而不在集合中存储至少部分结果。

给定一个输入集合,例如

List<String> list = ... ;

...很简单,只需两次传递,第一次获取最长的长度,第二次筛选具有该长度的字符串:

int longest = list.stream()
                  .mapToInt(String::length)
                  .max()
                  .orElse(-1);

List<String> result = list.stream()
                          .filter(s -> s.length() == longest)
                          .collect(toList());

如果输入是不能遍历一次以上的流,则可以使用收集器仅在一次传递中计算结果。编写这样一个收集器并不难,但由于要处理几个案例,所以有点乏味。在给定比较器的情况下,生成这样一个收集器的helper函数如下所示:

static <T> Collector<T,?,List<T>> 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中。不变量是任何这样的列表中的所有元素在比较器方面都是等效的。当添加一个元素时,如果它小于列表中的元素,则忽略它;如果相等,则添加;如果它更大,则清空列表并添加新元素。合并也不太难:返回包含较大元素的列表,但如果它们的元素相等,则追加列表。

给定一个输入流,这是非常容易使用的:

Stream<String> input = ... ;

List<String> result = input.collect(maxList(comparing(String::length)));
 类似资料:
  • 问题内容: 我已经max对Java 8 lambda和流上的功能进行了一些测试,并且似乎在max执行情况下,即使有多个对象与0比较,它也会在绑定的候选对象中返回任意元素,而无需进一步考虑。 对于这样的最大预期行为,是否有明显的技巧或功能,以便返回所有最大值?我在API中看不到任何内容,但是我确信它必须比手动比较更好。 例如: 问题答案: 我将按值分组并将值存储到TreeMap中,以便对值进行排序,

  • 问题内容: 阅读numpy中argmin函数的文档时,我有些困惑。看起来应该可以完成这项工作: 读这个 返回沿轴的最小值的索引。 我可能会认为 将返回所有索引的数组: 但是,它只会返回。渔获量在哪里,或者我应该怎么做才能得到结果? 问题答案: 当您考虑多维数组时,该文档更有意义。 在指定轴的情况下,沿给定轴获取一维子数组,并返回每个子数组最小值的第一个索引。它不会返回单个最小值的所有索引。 要获取

  • 问题内容: 表格示例: 所需的输出(不是确切的格式或上市顺序),每台计算机上每个应用程序的最新安装: 我的SQL语句: 这给了我: 并不是 如我所料。 如果我 仅 选择MAX(date),而没有其他选择,则MAX(date)有效。但是,那时我没有任何数据可以使用(仅是最新日期)。 我不是SQL忍者,所以我很快就会因此而挠头。 问题答案: 尝试这样: 内部查询是为您获取每对计算机和应用程序的max(

  • max 获得数据表中,值最大的max($table, $column, $where) table [string] 表名. column [string] 查询的字段列. where (optional) [array] WHERE 条件.max($table, $join, $column, $where) table [string] 表名. join [array] 多表查询. colum

  • max 获得数据表中,值最大的max($table, $column, $where) table [string] 表名. column [string] 查询的字段列. where (optional) [array] WHERE 条件.max($table, $join, $column, $where) table [string] 表名. join [array] 多表查询. colum

  • 问题内容: 即使很棘手,也可以在Java中强制进行垃圾回收吗?我知道;,;但是他们只建议做GC。我该如何强制GC? 问题答案: 最好的选择是调用,这只是向垃圾收集器提示你要它进行收集。由于垃圾收集器是不确定的,因此无法强制立即收集。