Java SE 8是否有Pairs或Tuples?

 喵咘噜_783 发布于 2023-01-08 13:07

我正在玩Java SE 8中的惰性函数操作,我想要一个对/元组map的索引,然后基于第二个元素,最后只输出索引.i(i, value[i])filtervalue[i]

我是否仍然要忍受这个问题:Java中的C++ Pair 相当于什么?在lambdas和溪流的大胆新时代?

更新:我提供了一个相当简化的示例,其中有一个由@dkatzel提供的简洁解决方案,其中一个答案如下.但是,它没有概括.因此,让我添加一个更一般的例子:

package com.example.test;

import java.util.ArrayList;
import java.util.stream.IntStream;

public class Main {

  public static void main(String[] args) {
    boolean [][] directed_acyclic_graph = new boolean[][]{
        {false,  true, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false,  true, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false,  true},
        {false, false, false, false, false, false}
    };

    System.out.println(
        IntStream.range(0, directed_acyclic_graph.length)
        .parallel()
        .mapToLong(i -> IntStream.range(0, directed_acyclic_graph[i].length)
            .filter(j -> directed_acyclic_graph[j][i])
            .count()
        )
        .filter(n -> n == 0)
        .collect(() -> new ArrayList(), (c, e) -> c.add(e), (c1, c2) -> c1.addAll(c2))
    );
  }

}

这给出了不正确的输出,[0, 0, 0]该输出对应于所有三列的计数false.我需要的是这三列的索引.应该是正确的输出[0, 2, 4].我怎样才能得到这个结果?

7 个回答
  • 您可以查看这些内置类:

    AbstractMap.SimpleEntry

    AbstractMap.SimpleImmutableEntry

    2023-01-08 13:08 回答
  • 似乎可以在不使用任何类型的Pair结构的情况下解决完整示例.关键是过滤列索引,谓词检查整个列,而不是将列索引映射到该列中的false条目数.

    执行此操作的代码在此处:

        System.out.println(
            IntStream.range(0, acyclic_graph.length)
                .filter(i -> IntStream.range(0, acyclic_graph.length)
                                      .noneMatch(j -> acyclic_graph[j][i]))
                .boxed()
                .collect(toList()));
    

    这导致其输出[0, 2, 4]是我认为OP请求的正确结果.

    还要注意boxed()的操作,箱int值到Integer对象.这使得人们可以使用预先存在的toList()收集器而不必写出自己进行装箱的收集器功能.

    2023-01-08 13:09 回答
  • Vavr(以前称为Javaslang)(http://www.vavr.io)也提供元组(直到大小为8)。这是Javadoc:https : //static.javadoc.io/io.vavr/vavr/0.9.0/io/vavr/Tuple.html。

    这是一个简单的示例:

    Tuple2<Integer, String> entry = Tuple.of(1, "A");
    
    Integer key = entry._1;
    String value = entry._2;
    

    为什么JDK本身至今没有简单的元组,这对我来说还是个谜。编写包装器类似乎每天都在做。

    2023-01-08 13:09 回答
  • 更新:这个答案是对原始问题的回答,Java SE 8是否有Pairs或Tuples?(并且隐含地,如果不是,为什么不呢?)OP已经用更完整的示例更新了问题,但似乎可以在不使用任何类型的Pair结构的情况下解决它.[OP注意:这是另一个正确答案.]


    最简洁的答案是不.您要么必须自己动手,要么引入实现它的几个库中的一个.

    Pair在Java SE中有一个类被提议并且至少被拒绝一次.在OpenJDK的一个邮件列表上查看此讨论主题.权衡并不明显.一方面,在其他库和应用程序代码中有许多Pair实现.这表明了一种需求,将这样的类添加到Java SE将增加重用和共享.另一方面,拥有一个Pair类会增加从Pairs和集合中创建复杂数据结构的诱惑,而不会创建必要的类型和抽象.(这是Kevin Bourillion从那个帖子中传出的消息.)

    我建议所有人都阅读整个电子邮件主题.它非常富有洞察力,没有任何损害.这很有说服力.当它开始时,我想,"是的,Java SE中应该有一个Pair类"但是当线程到达终点时我改变了主意.

    但请注意,JavaFX具有javafx.util.Pair类.JavaFX的API与Jav​​a SE API分开演变.

    从链接问题可以看出,Java中C++对的等价物是什么?有一个相当大的设计空间围绕着显然是如此简单的API.对象应该是不可变的吗?它们应该可序列化吗?他们应该具有可比性吗 班级应该是最终的吗?这两个元素应该订购吗?它应该是一个接口还是一个类?为什么要成对停止?为什么不是三元组,四元组或N元组?

    当然,元素的命名也是不可避免的:

    (a,b)

    (第一秒)

    (左右)

    (汽车,司机)

    (foo,bar)

    等等

    几乎没有提到的一个大问题是Pairs与原始的关系.如果您有一个(int x, int y)表示2D空间中某个点的基准面,则将其表示为Pair<Integer, Integer>消耗三个对象而不是两个32位字.此外,这些对象必须驻留在堆上,并且会产生GC开销.

    看起来很清楚,像Streams一样,对于原始的专业化对于Pairs来说是至关重要的.我们想看到:

    Pair
    ObjIntPair
    ObjLongPair
    ObjDoublePair
    IntObjPair
    IntIntPair
    IntLongPair
    IntDoublePair
    LongObjPair
    LongIntPair
    LongLongPair
    LongDoublePair
    DoubleObjPair
    DoubleIntPair
    DoubleLongPair
    DoubleDoublePair
    

    即使是IntIntPair仍然需要堆上的一个对象.

    当然,这些都让人联想到java.util.functionJava SE 8中软件包中功能接口的激增.如果你不想要一个膨胀的API,你会遗漏哪些?您也可以认为这还不够,而且Boolean应该添加专业化.

    我的感觉是,如果Java很久以前就已经添加了一个Pair类,那么它本来就很简单,甚至是简单的,并且它不会满足我们现在想象的许多用例.考虑如果在JDK 1.0时间框架中添加了Pair,它可能是可变的!(看看java.util.Date.)人们会对此感到高兴吗?我的猜测是,如果在Java中有一个Pair类,它将是有点排序 - 并非真正有用,并且每个人仍然会自己滚动以满足他们的需求,在外部库中会有各种Pair和Tuple实现,人们仍然在争论/讨论如何修复Java的Pair类.换句话说,就像我们今天在同一个地方.

    同时,正在进行一些工作来解决基本问题,即在JVM(最终是Java语言)中为值类型提供更好的支持.请参阅此值的状态文档.这是初步的,推测性的工作,它只涵盖了JVM角度的问题,但它背后已有相当多的思考.当然,不能保证这会进入Java 9,或者无论何时进入Java 9,但它确实显示了当前关于这个主题的思考方向.

    2023-01-08 13:09 回答
  • 由于您只关心索引,因此根本不需要映射到元组.为什么不编写一个使用数组中查找元素的过滤器?

         int[] value =  ...
    
    
    IntStream.range(0, value.length)
                .filter(i -> value[i] > 30)  //or whatever filter you want
                .forEach(i -> System.out.println(i));
    

    2023-01-08 13:09 回答
  • 是。

    Map.Entry可以用作一个Pair

    不幸的是,它对Java 8流没有帮助,因为问题是即使lambda可以接受多个参数,但Java语言仅允许返回单个值(对象或原始类型)。这意味着,每当您有流时,最终都会从上一个操作传递单个对象。这是Java语言中的一种不足,因为如果支持多个返回值并且流支持它们,那么流可以完成更好的非平凡任务。

    在那之前,只有很少的用途。

    EDIT 2018-02-12:在处理项目时,我编写了一个帮助器类,该类有助于处理在稍后需要的流中尽早拥有标识符的特殊情况,但介于两者之间的流部分对此一无所知。直到我避开释放它自身的它是在IdValue.java与单元测试IdValueTest.java

    2023-01-08 13:09 回答
  • 遗憾的是,Java 8没有引入对或元组.您当然可以使用org.apache.commons.lang3.tuple(我个人也会与Java 8结合使用),或者您可以创建自己的包装器.或使用地图.或类似的东西,正如你所接受的那个问题的公认答案中所解释的那样.

    2023-01-08 13:12 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有