首页 文章

Value 对的Java集合? (元组?)

提问于
浏览
274

我喜欢Java有一个Map,你可以在其中定义 Map 中每个条目的类型,例如 <String, Integer> .

我正在寻找的是一种集合,其中集合中的每个元素都是一对值 . 对中的每个值都可以有自己的类型(如上面的String和Integer示例),它是在声明时定义的 .

该集合将保持其给定的顺序,并且不会将其中一个值视为唯一键(如在 Map 中) .

基本上我希望能够定义 <String,Integer> 类型的ARRAY或任何其他2种类型 .

我意识到我可以创建一个只有2个变量的类,但这看起来过于冗长 .

我也意识到我可以使用2D数组,但由于我需要使用不同的类型,我必须使它们成为OBJECT的数组,然后我必须一直投射 .

我只需要在集合中存储对,所以每个条目只需要两个值 . 没有走类路线,这样的事情是否存在?谢谢!

17 回答

  • 28

    Map.Entry

    这些内置类也是一个选项 . 两者都实现Map.Entry接口 .

    UML diagram of Map.Entry interface with pair of implementing classes

  • 0

    扩展其他答案,通用不可变对应该有一个静态方法,以避免在调用构造函数时混乱代码:

    class Pair<L,R> {
          final L left;
          final R right;
    
          public Pair(L left, R right) {
            this.left = left;
            this.right = right;
          }
    
          static <L,R> Pair<L,R> of(L left, R right){
              return new Pair<L,R>(left, right);
          }
    }
    

    如果您将静态方法命名为“of”或“pairOf”,则代码会变得流畅,因为您可以编写:

    list.add(Pair.of(x,y)); // my preference
        list.add(pairOf(x,y)); // use with import static x.y.Pair.pairOf
    

    真正的耻辱是核心java库在这些事情上如此稀疏,你必须使用commons-lang或其他第三方来做这些基本的东西 . 升级到scala的另一个原因......

  • 14

    您所描述的首选解决方案是一对列表(即列表) .

    要完成此任务,您需要创建一个Pair类,以便在您的集合中使用 . 这是一个有用的实用程序类,可以添加到您的代码库中 .

    Sun JDK中提供类似于典型Pair类的功能的最接近的类是AbstractMap.SimpleEntry . 你可以使用这个类,而不是创建自己的Pair类,虽然你将不得不忍受一些尴尬的限制,我想大多数人会对此不以为然,因为它并不是SimpleEntry的预期角色 . 例如,SimpleEntry没有“setKey()”方法,也没有默认构造函数,因此您可能会发现它太有限了 .

    请记住,集合旨在包含单一类型的元素 . 相关的实用程序接口(例如Map)实际上不是集合(即Map不实现Collection接口) . 一对不会实现Collection接口,但显然是构建更大数据结构的有用类 .

  • 5

    只需要创建一个类

    class tuples 
    { 
    int x;
    int y;
    }
    

    然后创建元组的这些对象的列表

    List<tuples> list = new ArrayList<tuples>();
    

    所以你也可以用同样的方式实现其他新的数据结构 .

  • 4

    Apache常见的lang3有Pair类和这个线程中提到的其他几个库What is the equivalent of the C++ Pair<L,R> in Java?

    匹配原始问题的要求的示例:

    List<Pair<String, Integer>> myPairs = new ArrayList<Pair<String, Integer>>();
    myPairs.add(Pair.of("val1", 11));
    myPairs.add(Pair.of("val2", 17));
    
    //...
    
    for(Pair<String, Integer> pair : myPairs) {
      //following two lines are equivalent... whichever is easier for you...
      System.out.println(pair.getLeft() + ": " + pair.getRight());
      System.out.println(pair.getKey() + ": " + pair.getValue());
    }
    
  • 4

    那com.sun.tools.javac.util.Pair怎么样?

  • 83

    Java 9

    在Java 9中,您只需编写:Map.entry(key, value)即可创建不可变对 .

    Note: 此方法不允许键或值为null . 例如,如果要允许空值,则需要将其更改为: Map.entry(key, Optional.ofNullable(value)) .


    Java 8

    在Java 8中,您可以使用更通用的javafx.util.Pair来创建一个不可变的,可序列化的对 . 此类允许null键和null值 . (在Java 9中,此类包含在 javafx.base 模块中) . EDIT: As of Java 11, JavaFX has been decoupled from the JDK, so you'd need the additional maven artifact org.openjfx:javafx-base.


    Java 6

    在Java 6及更高版本中,您可以使用更详细的AbstractMap.SimpleImmutableEntry表示不可变对,或者AbstractMap.SimpleEntry表示可以更改其值的对 . 这些类还允许null键和null值,并且是可序列化的 .


    Android

    如果您正在为Android编写,只需使用Pair.create(key, value)创建一个不可变对 .


    Apache Commons

    Apache Commons Lang提供了有用的Pair.of(key, value)来创建一个不可变的,可比较的,可序列化的对 .


    Eclipse集合

    如果您正在使用包含基元的对,Eclipse Collections提供了一些非常有效的原始对类,这将避免所有低效的自动装箱和自动拆箱 .

    例如,您可以使用PrimitiveTuples.pair(int, int)创建IntIntPair,或使用PrimitiveTuples.pair(float, long)创建FloatLongPair .


    龙目岛项目

    使用Project Lombok,只需编写以下代码即可创建不可变对类:

    @Value
    public class Pair<K, V> {
        K key;
        V value;
    }
    

    Lombok将在生成的字节码中自动填写构造函数,getter, equals()hashCode()toString() 方法 . 如果您想要静态工厂方法而不是构造函数(例如 Pair.of(k, v) ),只需将注释更改为: @Value(staticConstructor = "of") .


    否则

    如果以上解决方案都没有浮动您的船,您只需复制并粘贴以下代码(与接受的答案中列出的类不同,它可以防止NullPointerExceptions):

    import java.util.Objects;
    
    public class Pair<K, V> {
    
        public final K key;
        public final V value;
    
        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }
    
        public boolean equals(Object o) {
            return o instanceof Pair && Objects.equals(key, ((Pair<?,?>)o).key) && Objects.equals(value, ((Pair<?,?>)o).value);
        }
    
        public int hashCode() {
            return 31 * Objects.hashCode(key) + Objects.hashCode(value);
        }
    
        public String toString() {
            return key + "=" + value;
        }
    }
    
  • 5

    您可以编写一个通用的Pair <A,B>类,并在数组或列表中使用它 . 是的,您必须编写一个类,但是您可以为所有类型重用相同的类,因此您只需要执行一次 .

  • 221

    在讨论键/值对时,我首先想到的是Properties Class,您可以将项目保存并加载到流/文件中 .

  • 10
  • 6

    AbstractMap.SimpleEntry

    你很容易找到这个:

    java.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();
    

    你怎么能填补它?

    java.util.Map.Entry<String,Integer> pair1=new java.util.AbstractMap.SimpleEntry<>("Not Unique key1",1);
    java.util.Map.Entry<String,Integer> pair2=new java.util.AbstractMap.SimpleEntry<>("Not Unique key2",2);
    pairList.add(pair1);
    pairList.add(pair2);
    

    这简化为:

    Entry<String,Integer> pair1=new SimpleEntry<>("Not Unique key1",1);
    Entry<String,Integer> pair2=new SimpleEntry<>("Not Unique key2",2);
    pairList.add(pair1);
    pairList.add(pair2);
    

    并且,在 createEntry 方法的帮助下,可以进一步减少详细程度:

    pairList.add(createEntry("Not Unique key1", 1));
    pairList.add(createEntry("Not Unique key2", 2));
    

    由于 ArrayList 不是最终的,因此可以将其子类化为公开 of 方法(以及前面提到的 createEntry 方法),从而导致语法简洁:

    TupleList<java.util.Map.Entry<String,Integer>> pair = new TupleList<>();
    pair.of("Not Unique key1", 1);
    pair.of("Not Unique key2", 2);
    
  • 251

    "Apache Commons Lang 3" Pair 类和相关的子类怎么样?

    import org.apache.commons.lang3.tuple.ImmutablePair;
        import org.apache.commons.lang3.tuple.Pair;
        ...
        @SuppressWarnings("unchecked")
        Pair<String, Integer>[] arr = new ImmutablePair[]{
                ImmutablePair.of("A", 1),
                ImmutablePair.of("B", 2)};
    
        // both access the 'left' part
        String key = arr[0].getKey();
        String left = arr[0].getLeft();
    
        // both access the 'right' part
        Integer value = arr[0].getValue();
        Integer right = arr[0].getRight();
    

    ImmutablePair 是一个特定的子类,它不允许修改对中的值,但是还有其他实现具有不同的语义 . 如果需要,这些是Maven坐标 .

    <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.4</version>
            </dependency>
    
  • 6

    这是基于JavaHelp4u的代码 .

    不那么冗长,并说明如何在一行中完成以及如何循环 .

    //======>  Imports
    import java.util.AbstractMap.SimpleEntry;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map.Entry;
    
    //======>  Single Entry
    SimpleEntry<String, String> myEntry = new SimpleEntry<String, String>("ID", "Text");
    System.out.println("key: " + myEntry.getKey() + "    value:" + myEntry.getValue());
    System.out.println();
    
    //======>  List of Entries
    List<Entry<String,String>> pairList = new ArrayList<>();
    
    //-- Specify manually
    Entry<String,String> firstButton = new SimpleEntry<String, String>("Red ", "Way out");
    pairList.add(firstButton);
    
    //-- one liner:
    pairList.add(new SimpleEntry<String,String>("Gray", "Alternate route"));  //Ananomous add.
    
    //-- Iterate over Entry array:
    for (Entry<String, String> entr : pairList) {
        System.out.println("Button: " + entr.getKey() + "    Label: " + entr.getValue());
    }
    
  • 0

    我的意思是,即使Java中没有 Pair 类,也有类似的东西: Map.Entry

    Map.Entry Documentation

    这是(简化了很多) HashMap ,或实际上任何 Map 存储 .

    您可以创建一个 Map 实例来存储您的值并获取条目集 . 你最终会得到 Set<Map.Entry<K,V>> ,这实际上就是你想要的 .

    所以:

    public static void main(String []args)
    {    
        HashMap<String, Integer> values = new HashMap<String,Integer>();
        values.put("A", 235);//your custom data, the types may be different
        //more data insertions....
        Set<Map.Entry<String,Integer>> list = values.entrySet();//your list 
        //do as you may with it
    }
    
  • 55

    Pair类是那些“gimme”泛型示例之一,很容易自己编写 . 例如,我的头顶:

    public class Pair<L,R> {
    
      private final L left;
      private final R right;
    
      public Pair(L left, R right) {
        this.left = left;
        this.right = right;
      }
    
      public L getLeft() { return left; }
      public R getRight() { return right; }
    
      @Override
      public int hashCode() { return left.hashCode() ^ right.hashCode(); }
    
      @Override
      public boolean equals(Object o) {
        if (!(o instanceof Pair)) return false;
        Pair pairo = (Pair) o;
        return this.left.equals(pairo.getLeft()) &&
               this.right.equals(pairo.getRight());
      }
    
    }
    

    是的,它存在于网络的多个位置,具有不同程度的完整性和功能 . (我上面的例子是不可变的 . )

  • 3

    我打算问你是否不想只使用 List<Pair<T, U>> ?但是,当然,JDK没有Pair <>类 . 但是一个快速的谷歌在Wikipediaforums.sun.com上找到了一个 . 干杯

  • 17

    对于开发Android的任何人,您都可以使用android.util.Pair . :)

相关问题