在Java中使用Pairs或2元组

syk*_*ker 293 java tuples

Java中的Hashtable将受益于具有元组结构的值.我可以在Java中使用哪种数据结构来做到这一点?

Hashtable<Long, Tuple<Set<Long>,Set<Long>>> table = ...
Run Code Online (Sandbox Code Playgroud)

mae*_*ics 307

我不认为Java中有一个通用的元组类,但自定义元组可能就像下面这样简单:

public class Tuple<X, Y> { 
  public final X x; 
  public final Y y; 
  public Tuple(X x, Y y) { 
    this.x = x; 
    this.y = y; 
  } 
} 
Run Code Online (Sandbox Code Playgroud)

当然,如何在平等性,不变性等方面进一步设计这个类有一些重要的含义,特别是如果你打算使用实例作为散列的键.

  • 我认为最好将`x`和`y`声明为`public final`并摆脱那些吸气剂. (61认同)
  • 那不是一个元组.它只保持对(长度为2的元组). (50认同)
  • @YagoMéndezVidal:是的,我的回答的最后一句话说"如果你在平等,不变性等方面进一步设计这个类有一些重要的含义,特别是如果你打算用实例作为散列的关键." (34认同)
  • 这不起作用.当在Hashtable或HashMap(根据请求)中使用时,它会失败,因为具有相同元素的2个不同元组将提供不同的哈希码.必须覆盖`equals()`和`hashCode()`. (20认同)
  • 我在 C# 中经常使用元组,如果您想为自己编写一个更大的元组,该文档非常好:http://msdn.microsoft.com/de-de/library/vstudio/dd387036.aspx (2认同)

小智 162

javatuples是Java 中元组的专用项目.

Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Run Code Online (Sandbox Code Playgroud)

  • 它只覆盖10元组的元组吗? (6认同)
  • @ n611x007,我认为每个元组变体都是手写的(即,您不能用可变数量的类型参数来编写Java代码,至少不容易),因此对于库编写器来说,停在某个地方很有意义,似乎是10像支持大多数用例的合理数量。 (3认同)
  • javatuple库的一些引人注目的特性如其网站所述 - 所有元组类都是:Typesafe,Immutable,Iterable,Serializable,Comparable(实现Comparable <Tuple>),实现equals(...)和hashCode(),并实现toString().知道可能有用. (2认同)

rhg*_*hgb 93

Apache Commons提供了一些常见的Java实用程序,包括一.它实现Map.Entry,ComparableSerializable.

  • 嗯,关于元组的问题似乎是错误的.对!=元组.元组是*n* - 长度,即.任何长度. (5认同)
  • Apache Commons提供的实现完全符合我的需要.我很高兴有一个有效的实施. (2认同)
  • 注意*Android开发人员* - Android SDK已经实现了从API 5或API 4(支持库)支持的genric [Pair class](https://developer.android.com/reference/android/util/Pair.html) ). (2认同)

小智 56

如果您正在寻找内置的Java双元素元组,请尝试AbstractMap.SimpleEntry.

  • 不太可读.如果我在代码中看到这个,我会想知道地图在哪里. (32认同)
  • 如果可读性是一个问题,你也可以像这样创建自己的元组:`class Tuple extends AbstractMap.SimpleEntry {}`然后你可以将类称为`Tuple`. (5认同)
  • 虽然这个类的目的是为了便于根据javadoc创建自定义地图实现,但这可以很好地完成工作.+1.此外,在这种情况下,可读性不是*那么大的问题. (2认同)
  • @ dimo414:因为SimpleEntry已经实现了equals,hashcode并且拥有其他所需的一切.如果你想要一个通用的`Tuple`,那么`key`和`value`可能是好名字,结果可能已经完全是你需要的了.当然,如果情况并非如此,那么你当然认为自定义实现是一个好主意. (2认同)

Ara*_*yan 38

作为@maerics很好的答案的扩展,我添加了一些有用的方法:

public class Tuple<X, Y> { 
    public final X x; 
    public final Y y; 
    public Tuple(X x, Y y) { 
        this.x = x; 
        this.y = y; 
    }

    @Override
    public String toString() {
        return "(" + x + "," + y + ")";
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }

        if (!(other instanceof Tuple)){
            return false;
        }

        Tuple<X,Y> other_ = (Tuple<X,Y>) other;

        // this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed.
        return other_.x.equals(this.x) && other_.y.equals(this.y);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((x == null) ? 0 : x.hashCode());
        result = prime * result + ((y == null) ? 0 : y.hashCode());
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @YagoMéndezVidal,你的意思是`Objects.equals(other.x,this.x)`等等?该方法接受两个Object引用作为参数,而不是布尔值. (4认同)
  • 如果x或y是String,则equals方法将无效. (3认同)
  • 正如athabaska所指出的,只需将`equals()`的最后一行替换为`在Java 7中返回Objects.equals(other_.x == this.x)&& Objects.equals(other_.y == this.y)`或与null检查相等的比较. (3认同)

Teo*_*ali 29

另外2美分:从Java 7开始,现在标准Lib中有一个类:javafx.util.Pair.

是的,它是标准的Java,现在JavaFx包含在JDK中:)

  • 这是一个丑陋的黑客.那么你是否会成对配对一对4元组? (19认同)
  • Aaaand将在JDK 9中使用拼图.我的意思是你仍然可以使用它,但是你真的想将javafx包含在你的项目中吗?因为这个类?:) (11认同)
  • 在这里,我仍然希望javafx(Properties,Pair等)的"实用程序"部分将迁移到java的核心,或者至少迁移到特定的模块 (3认同)
  • 遗憾的是,javafx 很快就会再次从 JRE 中删除。 (3认同)

not*_*eti 17

以下是其他地方完全相同的问题,其中包括更强大的内容equals,hash这些内容暗示:

http://groups.google.com/group/comp.lang.java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b

那个讨论继续反映了maerics和ColinD的方法"我应该重新使用一个具有非特定名称的类元组,或者在每次遇到这种情况时创建一个具有特定名称的新类".多年前我在后一个营地; 我已经发展成为支持前者.

  • 你可以在关闭组或其他任何组合之前粘贴相关部分吗?因此,我们鼓励将相关信息复制到现场. (2认同)

小智 9

使用lombok可以很容易地声明一个Pair类:

@Data(staticConstructor = "of")
public class Pair<A, B> {
    private final A left;
    private final B right;
}
Run Code Online (Sandbox Code Playgroud)

这将生成getter,名为"of"的静态构造函数equals(),hashcode()toString().

@Data有关更多信息,请参阅文档

  • @user180100,关于“使用 lombok 很容易”;但去龙目岛容易吗? (2认同)

see*_*851 7

Android Tuple Utils

此对象提供equals()的合理实现,如果equals()在每个包含的对象上为true,则返回true.


Mad*_*sen 7

虽然这篇文章现在已经很老了,而且我知道我并不是真的很有帮助,但我认为《向 Java 添加元组:轻量级数据结构的研究》中描述的建议在主流 Java 中会很好。

您可以执行以下操作:

int a;
char b;
float c;
[a,b,c] = [3,'a',2.33];
Run Code Online (Sandbox Code Playgroud)

或者

[int,int,char] x = [1,2,'a'];
Run Code Online (Sandbox Code Playgroud)

或者

public [int,boolean] Find(int i)
{
  int idx = FindInArray(A,i);
  return [idx,idx>=0];
}

[idx, found] = Find(7);
Run Code Online (Sandbox Code Playgroud)

这里的元组是:

  • 定义为原始类型 - 无模板/泛型
  • 如果本地声明则堆栈分配
  • 使用模式匹配分配

这种方法增加了

  • 表现
  • 可读性
  • 表现力

  • Java 社区中有一些围绕此问题的活动。例如,请参见:https://blogs.oracle.com/jrose/entry/tuples_in_the_vm (2认同)

Col*_*inD 6

创建一个类,描述您实际建模和使用它的概念.它可以只存储两个Set<Long>并为它们提供访问器,但是它应该被命名以指示每个集合的确切内容以及它们为什么被组合在一起.


Ale*_*nko 5

为了补充@ maerics的答案,这里是Comparable元组:

import java.util.*;

/**
 * A tuple of two classes that implement Comparable
 */
public class ComparableTuple<X extends Comparable<? super X>, Y extends Comparable<? super Y>>
       extends Tuple<X, Y>
       implements Comparable<ComparableTuple<X, Y>>
{
  public ComparableTuple(X x, Y y) {
    super(x, y);
  }

  /**
   * Implements lexicographic order
   */
  public int compareTo(ComparableTuple<X, Y> other) {
    int d = this.x.compareTo(other.x);
    if (d == 0)
      return this.y.compareTo(other.y);
    return d;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这也是因为元组应该是Pairs这个问题的错误假设......元组有任何长度,而不仅仅是2. (4认同)
  • @AlexeiAverchenko,是一组4对Tuple-5,*总*........ (4认同)