Usando pares o 2-tuplas en Java

Mi Hashtable en Java se beneficiaría de un valor que tenga una estructura de tupla. ¿Qué estructura de datos puedo usar en Java para hacer eso?

Hashtable<Long, Tuple<Set,Set>> table = ... 

No creo que haya una clase de tupla de propósito general en Java, pero una personalizada puede ser tan fácil como la siguiente:

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

Por supuesto, hay algunas implicaciones importantes de cómo diseñar esta clase aún más con respecto a la igualdad, inmutabilidad, etc., especialmente si planea usar instancias como claves para hash.

javatuples es un proyecto dedicado para tuplas en Java.

 Unit (1 element) Pair (2 elements) Triplet (3 elements) 

Apache Commons proporcionó algunas utilidades comunes de Java, incluido un par . Implementa Map.Entry , Comparable y Serializable .

Si está buscando una tupla Java integrada de dos elementos, pruebe AbstractMap.SimpleEntry .

Como una extensión de la simpática respuesta de @maerics, agregué algunos métodos útiles:

 public class Tuple { 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 other_ = (Tuple) 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; } } 

Otros 2 centavos: comenzando con Java 7, ahora hay una clase para esto en Lib estándar: javafx.util.Pair.

Y sí, es Java estándar, ahora que JavaFx está incluido en el JDK 🙂

Aquí está exactamente la misma pregunta en otro lugar, que incluye un equals más robusto, hash que maerics alude:

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

Esa discusión continúa para reflejar los enfoques maerics vs ColinD de “¿debería volver a utilizar una clase Tuple con un nombre no específico, o hacer una nueva clase con nombres específicos cada vez que me encuentro con esta situación”. Hace años yo estaba en el último campamento; He evolucionado para apoyar al primero.

Android Tuple Utils

Este objeto proporciona una implementación sensata de equals (), que devuelve verdadero si equals () es verdadero en cada uno de los objetos contenidos.

Cree una clase que describa el concepto en el que está realmente modelando y use eso. Solo puede almacenar dos Set y proporcionarles acceso, pero debe tener un nombre para indicar exactamente qué es cada uno de esos conjuntos y por qué están agrupados.

Para complementar la respuesta de @maerics, aquí está la tupla Comparable :

 import java.util.*; /** * A tuple of two classes that implement Comparable */ public class ComparableTuple, Y extends Comparable> extends Tuple implements Comparable> { public ComparableTuple(X x, Y y) { super(x, y); } /** * Implements lexicographic order */ public int compareTo(ComparableTuple other) { int d = this.x.compareTo(other.x); if (d == 0) return this.y.compareTo(other.y); return d; } } 

Con lombok es fácil declarar una clase Pair :

 @Data(staticConstructor = "of") public class Pair { private final A left; private final B right; } 

Esto generará getters, constructor estático llamado “de”, equals() , hashcode() y toString() .

vea la documentación de @Data para más información

Puedes usar Google Guava Table

Aunque el artículo es bastante viejo ahora, y aunque entiendo que no soy realmente muy útil, creo que el trabajo se hace aquí: http://www.pds.ewi.tudelft.nl/pubs/papers/cpe2005.pdf , habría sido bueno en la stream principal de Java.

Puedes hacer cosas como:

 int a; char b; float c; [a,b,c] = [3,'a',2.33]; 

o

 [int,int,char] x = [1,2,'a']; 

o

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

Aquí las tuplas son:

  • Definido como tipos primitivos – sin plantillas / generics
  • Asignado de stack si se declara localmente
  • Asignado mediante el patrón de coincidencia

Este enfoque aumenta

  • Actuación
  • Legibilidad
  • Expresividad

Comenzaré desde un punto de vista general sobre las tuplas en Java y terminaré con una implicación para su problema concreto.

1) La forma en que se usan las tuplas en los lenguajes no generics se evita en Java porque no son seguras para tipos (por ejemplo, en Python: tuple = (4, 7.9, 'python') ). Si aún desea usar algo como una tupla de propósito general (que no se recomienda ), debe usar Object[] o List y emitir los elementos después de una comprobación con instanceof para garantizar la seguridad del tipo.

Por lo general, las tuplas en una configuración determinada siempre se usan de la misma manera con la misma estructura. En Java, debe definir esta estructura explícitamente en una class para proporcionar valores y métodos bien definidos y seguros. Esto parece molesto e innecesario al principio, pero previene errores ya en tiempo de comstackción .

2) Si necesita una tupla que contenga las mismas (super-) clases Foo , use Foo[] , List , o List List (o las contrapartes inmutables de la lista). Como una tupla no tiene una longitud definida, esta solución es equivalente.

3) En su caso, parece que necesita un Pair (es decir, una tupla de longitud bien definida 2). Esto hace que la respuesta de maerics o una de las respuestas suplementarias sea la más eficiente ya que puede reutilizar el código en el futuro.