¿Hay una buena razón por la cual no hay Pair<L,R>
en Java? ¿Cuál sería el equivalente de esta construcción C ++? Prefiero evitar reimplementar el mío.
Parece que 1.6 está proporcionando algo similar ( AbstractMap.SimpleEntry<K,V>
), pero esto parece bastante complicado.
AbstractMap.SimpleEntry
complicado?Respuestas:
En un hilo
comp.lang.java.help
, Hunter Gratzner da algunos argumentos en contra de la presencia de unaPair
construcción en Java. El argumento principal es que una clasePair
no transmite ninguna semántica sobre la relación entre los dos valores (¿cómo sabe lo que significa "primero" y "segundo"?).Una mejor práctica es escribir una clase muy simple, como la que propuso Mike, para cada aplicación que hubiera hecho de la
Pair
clase.Map.Entry
es un ejemplo de una pareja que lleva su significado en su nombre.En resumen, en mi opinión, es mejor tener una clase
Position(x,y)
, una claseRange(begin,end)
y una clase enEntry(key,value)
lugar de un genéricoPair(first,second)
que no me diga nada sobre lo que se supone que debe hacer.fuente
Esto es Java Debe crear su propia clase Pair personalizada con nombres descriptivos de clase y campo, y no debe preocuparse de que reinvente la rueda escribiendo hashCode () / equals () o implementando Comparable una y otra vez.
fuente
SimpleImmutableEntry
Clase de par compatible con HashMap:
fuente
super()
. Normalmente lo cortaría si es opcional, como si estuviera aquí.El par más corto que se me ocurrió es el siguiente, utilizando Lombok :
Tiene todas las ventajas de la respuesta de @arturh (excepto la comparabilidad), tiene
hashCode
,equals
,toString
y un “constructor” estática.fuente
Apache Commons Lang 3.0+ tiene algunas clases de pares: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
fuente
Otra forma de implementar Emparejar con.
Fábrica simple para que no tenga que proporcionar los tipos. por ejemplo, Pair.of ("hola", 1);
fuente
of
. Recuerda las colecciones inmutables de Google Guava .o1
aComparable
, aunque nada indica que en realidad va a poner en práctica esa interfaz. Si ese es un requisito, elFIRST
parámetro tipo debería serloFIRST extends Comparable<?>
.¿Qué tal http://www.javatuples.org/index.html? Lo he encontrado muy útil.
El javatuples le ofrece clases de tuplas de uno a diez elementos:
fuente
Pair
y podría imaginar usarTriplet
tal vez una vez cada 50 años. Ahora uso Lombok y creo una pequeña clase de 4 líneas cada vez que necesito un par. Entonces "10 demasiado" es exacto.Bottom (0 element)
clase? :)Depende de para qué lo quieras usar. La razón típica para hacerlo es iterar sobre los mapas, para lo cual simplemente debe hacer esto (Java 5+):
fuente
android proporciona la
Pair
clase ( http://developer.android.com/reference/android/util/Pair.html ), aquí la implementación:fuente
Objects.equal(..)
requiere la biblioteca de guayaba.Objects.equals(...)
que ha estado en Java desde 2011 (1.7).El mayor problema es probablemente que uno no puede garantizar la inmutabilidad en A y B (consulte Cómo asegurarse de que los parámetros de tipo sean inmutables ), por lo que
hashCode()
puede dar resultados inconsistentes para el mismo par después de que se inserte en una colección, por ejemplo (esto daría un comportamiento indefinido , vea Definir iguales en términos de campos mutables ). Para una clase de par particular (no genérica), el programador puede garantizar la inmutabilidad eligiendo cuidadosamente A y B para que sean inmutables.De todos modos, borrando las advertencias genéricas de la respuesta de @ PeterLawrey (java 1.7):
Adiciones / correcciones muy bienvenidas :) En particular, no estoy muy seguro acerca de mi uso de
Pair<?, ?>
.Para obtener más información sobre por qué esta sintaxis, consulte Asegúrese de que los objetos implementen Comparable y para una explicación detallada ¿Cómo implementar una
max(Comparable a, Comparable b)
función genérica en Java?fuente
En mi opinión, no hay un par en Java porque, si desea agregar funcionalidad adicional directamente en el par (por ejemplo, comparable), debe vincular los tipos. En C ++, simplemente no nos importa, y si los tipos que componen un par no tienen
operator <
, elpair::operator <
no se compilará también.Un ejemplo de Comparable sin límite:
Un ejemplo de Comparable con la verificación en tiempo de compilación para determinar si los argumentos de tipo son comparables:
Esto es bueno, pero esta vez no puede usar tipos no comparables como argumentos de tipo en Par. Uno puede usar muchos comparadores para pares en alguna clase de utilidad, pero las personas de C ++ pueden no obtenerlo. Otra forma es escribir muchas clases en una jerarquía de tipos con diferentes límites en los argumentos de tipo, pero hay demasiados límites posibles y sus combinaciones ...
fuente
JavaFX (que viene incluido con Java 8) tiene la clase Pair <A, B>
fuente
hashCode()
. Tenga en cuenta que Java en sí no llama a este método. Es para el código de usuario, incluidas las bibliotecas.Como muchos otros ya han dicho, realmente depende del caso de uso si una clase Pair es útil o no.
Creo que para una función auxiliar privada es totalmente legítimo usar una clase Pair si eso hace que su código sea más legible y no vale la pena el esfuerzo de crear otra clase de valor con todo su código de placa de caldera.
Por otro lado, si su nivel de abstracción requiere que documente claramente la semántica de la clase que contiene dos objetos o valores, entonces debe escribir una clase para ello. Por lo general, ese es el caso si los datos son un objeto comercial.
Como siempre, requiere un juicio experto.
Para su segunda pregunta, recomiendo la clase Pair de las bibliotecas de Apache Commons. Esos podrían considerarse como bibliotecas estándar extendidas para Java:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
También es posible que desee echar un vistazo a EqualsBuilder , HashCodeBuilder y ToStringBuilder de Apache Commons , que simplifican la escritura de clases de valor para sus objetos comerciales.
fuente
Puede usar la clase de utilidad javafx,
Pair
que sirve para el mismo propósito que el par <> en c ++. https://docs.oracle.com/javafx/2/api/javafx/util/Pair.htmlfuente
Buenas noticias
JavaFX
tiene un valor clave Par.simplemente agregue javafx como dependencia e importe
javafx.util.Pair
;y usar simplemente como en
c++
.p.ej
fuente
La interfaz Map.Entry se acerca bastante al par c ++. Mire la implementación concreta, como AbstractMap.SimpleEntry y AbstractMap.SimpleImmutableEntry El primer elemento es getKey () y el segundo es getValue ().
fuente
fuente
De acuerdo con la naturaleza del lenguaje Java, supongo que las personas no requieren realmente
Pair
una interfaz, generalmente es lo que necesitan. Aquí hay un ejemplo:Entonces, cuando las personas desean devolver dos valores, pueden hacer lo siguiente:
Esta es una solución bastante ligera y responde a la pregunta "¿Cuál es la semántica de un
Pair<L,R>
?". La respuesta es, esta es una compilación de interfaz con dos (puede ser diferente) tipos, y tiene métodos para devolver cada uno de ellos. Depende de usted agregarle más semántica. Por ejemplo, si está utilizando Posición y REALMENTE desea indicarlo en su código, puede definirPositionX
yPositionY
que contieneInteger
, para componer aPair<PositionX,PositionY>
. Si JSR 308 está disponible, también puede usarloPair<@PositionX Integer, @PositionY Ingeger>
para simplificar eso.EDITAR: Una cosa que debo indicar aquí es que la definición anterior relaciona explícitamente el nombre del parámetro de tipo y el nombre del método. Esta es una respuesta a los argumentos de que a
Pair
es falta de información semántica. En realidad, el métodogetL
significa "dame el elemento que corresponde al tipo de parámetro tipo L", que significa algo.EDITAR: Aquí hay una clase de utilidad simple que puede hacer la vida más fácil:
uso:
fuente
equals
,hashCode
ytoString
?toString
necesita más conocimiento sobre la relación entre los dos campos.class
podría ser mejor que solointerface
porque puede implementar estas cosas.A pesar de ser sintácticamente similares, Java y C ++ tienen paradigmas muy diferentes. Escribir C ++ como Java es malo C ++, y escribir Java como C ++ es malo Java.
Con un IDE basado en la reflexión como Eclipse, escribir la funcionalidad necesaria de una clase de "par" es rápido y simple. Cree una clase, defina dos campos, use las diversas opciones de menú "Generar XX" para completar la clase en cuestión de segundos. Tal vez tendrías que escribir un "compareTo" muy rápido si quisieras la interfaz Comparable.
Con opciones separadas de declaración / definición en el lenguaje, los generadores de código C ++ no son tan buenos, por lo que escribir a mano pequeñas clases de utilidad es más tedioso. Debido a que el par es una plantilla, no tiene que pagar por funciones que no usa, y la función typedef permite asignar nombres de tipo significativos al código, por lo que las objeciones sobre "sin semántica" realmente no se sostienen.
fuente
El par sería una buena cosa, para ser una unidad de construcción básica para un genérico complejo, por ejemplo, esto es de mi código:
Es lo mismo que la Tupla de Haskell
fuente
Pair
es óptimo ya que no hay una semántica especial. Tener un nombre claro para un concepto claro es bueno, pero buscar un nombre donde "primero" y "segundo" funcionan bien no lo es.Manera simple Object [] - puede usarse como cualquier tupla de dimensión
fuente
Para lenguajes de programación como Java, la estructura de datos alternativa utilizada por la mayoría de los programadores para representar pares como estructuras de datos son dos matrices, y se accede a los datos a través del mismo índice
ejemplo: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
Esto no es ideal ya que los datos deben estar unidos, pero también resultan ser bastante baratos. Además, si su caso de uso exige el almacenamiento de coordenadas, es mejor construir su propia estructura de datos.
Tengo algo como esto en mi biblioteca
fuente
Puede usar la biblioteca AutoValue de Google: https://github.com/google/auto/tree/master/value .
Crea una clase abstracta muy pequeña y la anota con @AutoValue y el procesador de anotaciones genera una clase concreta para usted que tiene un valor semántico.
fuente
Aquí hay algunas bibliotecas que tienen múltiples grados de tuplas para su conveniencia:
Se ha mencionado que otras bibliotecas contienen al menos el
Pair
tupla.Específicamente, en el contexto de la programación funcional que utiliza una gran cantidad de tipeo estructural, en lugar de tipeo nominal ( como se recomienda en la respuesta aceptada ), esas bibliotecas y sus tuplas son muy útiles.
fuente
Brian Goetz, Paul Sandoz y Stuart Marks explican por qué durante la sesión de control de calidad en Devoxx'14.
Tener una clase de pares genéricos en la biblioteca estándar se convertirá en deuda técnica una vez que se introduzcan los tipos de valor .
Ver también: ¿Java SE 8 tiene pares o tuplas?
fuente
otra implementación concisa de lombok
fuente
Noté que todas las implementaciones de Par esparcidas por aquí atribuyen significado al orden de los dos valores. Cuando pienso en un par, pienso en una combinación de dos elementos en los que el orden de los dos no tiene importancia. Aquí está mi implementación de un par desordenado, con
hashCode
yequals
reemplaza para garantizar el comportamiento deseado en las colecciones. También se puede clonar.Esta implementación se ha probado correctamente en la unidad y se ha probado su uso en un conjunto y un mapa.
Tenga en cuenta que no pretendo publicar esto en el dominio público. Este es un código que acabo de escribir para usarlo en una aplicación, por lo que si va a usarlo, evite hacer una copia directa y juegue un poco con los comentarios y los nombres. ¿Me entiendes?
fuente
Si alguien quiere una versión simple y fácil de usar, la puse a disposición en https://github.com/lfac-pt/Java-Pair . Además, las mejoras son muy bienvenidas!
fuente
com.sun.tools.javac.util.Pair es una implementación simple de un par. Se puede encontrar en jdk1.7.0_51 \ lib \ tools.jar.
Aparte de org.apache.commons.lang3.tuple.Pair, no es solo una interfaz.
fuente
uso:
¡Inmutable, solo un par!
fuente
Pair<Object, Object> pair = Pair.createPair("abc", "def")
pero creo que uno necesita escribirPair.createPair((Object)"abc", (Object)"def")
con su código?@SuppressWarnings("unchecked") public static <K, V, X, Y> Pair<X, Y> createPair(K key, V value) { return new Pair<X, Y>((X) key, (Y) value); }
pero no sé si es una buena prácticanew Pair<Object, Object>("abc", "def")
fue lo más confiable en mis experimentos.