2011-06-07 20 views
43

Este es un problema pequeño, ya que podría fácilmente aumentar un par de clases para hacer el trabajo. No obstante, realmente no quiero hacer esto, y creo que debería haber alguna forma simple, incorporada, similar a una java de devolver dos valores. ¿Cuál es la mejor y más simple forma de hacer esto? Arrays? Alguna otra estructura de datos?¿Cuál es la mejor manera de devolver un par de valores en Java?

+8

El modo Java _es_ crear tantas clases como sea posible: p (Solo parcialmente como una broma ...) –

+0

Véase también el tema relacionado pero distinto http://stackoverflow.com/questions/457775/does-java- necesitar-tuplas. –

+0

Relacionado: https://stackoverflow.com/questions/2832472/how-to-return-2-values-from-a-java-method –

Respuesta

29

Por lo que yo sé, no es por desgracia ninguna representación integrada de un par en Java (y desde luego me gustaría que hubiera). Personalmente, cuando codigo un proyecto en el que encuentro que una clase de par a menudo sería útil, creo una clase genérica Pair<T, U> (que probablemente sea en lo que estabas pensando). Devolver una matriz es una manera rápida y sencilla, pero es posible que lamentemos más tarde, porque las personas que usan su método se preguntan si el método podría devolver más de dos valores en algún momento.

Cualquiera que sea la solución que elija: cada vez que sienta que necesita un par, debe considerar si el tiempo ahorrado hoy mediante, p. Ej. una clase de par genérica realmente vale la pérdida de información para la siguiente persona que lea el código (y esa persona puede ser usted en seis meses). Escribir una clase separada para el tipo de devolución toma más tiempo ahora, pero transmitiría más información a aquellos que usan su método (es decir, les dice a los usuarios qué representa el valor de retorno, y contiene nombres de miembros útiles para los dos valores). Sin embargo, si se trata de un método no público que se usa solo en algunos lugares, un par es más aceptable.

+3

Pero si eres el tipo de persona que se nutre de la confusión, ¡puedes anidar esos pares! Por ejemplo, devuelva un Pair >> –

+2

@Sam Barnum: Ciertamente, y admito que lo he hecho algunas veces. : p No es muy agradable mirar más adelante, sin embargo ... (Por otro lado, en LISP, todas las listas están representadas de esta manera, solo que con una sintaxis más bonita.) –

+1

@Sam Barnum, me encanta anidar Parejas de parejas de Pears también! – Atreys

-1

si ambos son números enteros entonces yo aconsejaría un java.awt.Point pero por lo demás es crear una clase de contenedor con dos objetos X e Y

+4

Lo recomendaría en contra de esto, porque haría que todos los que leen la declaración del método cree que el valor de retorno representa un punto geométrico. –

+1

En el contexto en el que estoy trabajando en este momento, creo que esta es una buena solución, ya que estoy devolviendo dos enteros. Me olvidé de Point, gracias por mencionarlo. – Graham

+5

@ Graham: Si los dos enteros realmente representan un punto geométrico, está bien; de lo contrario, la persona que lea su código en seis meses (y esta persona podría ser usted mismo) creerá erróneamente que su método arroja un punto geométrico (mientras realmente devuelve, por ejemplo, el cociente y el resto de una operación de división), y el tiempo que perderá debido a ese malentendido superará fácilmente el tiempo que le tomará hoy para crear una clase Pair o una clase más específica. Nunca use una clase solo porque "tiene campos del tipo correcto". –

12

lo más parecido que he visto a un "par" en la norma las bibliotecas son la interfaz Map.Entry y las clases AbstractMap.SimpleEntry y AbstractMap.SimpleImmutableEntry que lo implementan.

Si ambos objetos son de la misma clase, una matriz es más fácil de usar.

25

Usar una clase de contenedor es la forma más fácil.

public class Pair<T, U> {   
    public final T t; 
    public final U u; 

    public Pair(T t, U u) {   
     this.t= t; 
     this.u= u; 
    } 
} 
2

tres enfoques, todos los no tan grandes:

  1. rodar su propia Pair<A, B>. Dijiste que no querías hacer eso.
  2. Devuelva Object[]. Esto no es seguro.
  3. Mimic variables o punteros mediante el suministro de matrices de elemento único como parámetros.

Un ejemplo de # 3:

public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) { 
    assert lastName != null && lastName.length == 1; 
    assert firstName != null && firstName.length == 1; 
    assert dob  != null && dob.length  == 1; 
    ... 
} 

La tercera opción hace que la vida doloroso para la persona que llama.

Así que como dije, no hay una solución agradable.

Como un lado, Scala usa varias clases de Tuple (hasta 21 tuplas, por lo que recuerdo) para ayudarte con esto.

0

Me han dicho por los expertos que cuando se enfrentan a la cuestión de pares, una de las dos cosas es cierta:

  1. Usted necesidad de replantear su estructura (esta respuesta contundente no ayuda a nadie)
  2. Usted necesita construir su propia clase para mantener el par

Yo sugeriría que el segundo caso no es tan anormal. Sin embargo, si lo que está haciendo parece demasiado trivial para introducir una nueva clase, entonces podría funcionar Map, como otros han sugerido. Si simplemente está enviando una sola respuesta, entonces un Map parece un poco demasiado.

Si una lista de pares parece que funcionaría, y necesita mantener el orden, puede intentar con un LinkedHashMap para que se mantenga el orden.

+0

Si desea abusar de los mapas para devolver pares, ¿por qué no simplemente utilizar SimpleImmutableEntry de AbstractMap? https://docs.oracle.com/javase/8/docs/api/java/util/AbstractMap.SimpleImmutableEntry.html Está completamente sin información sobre qué es el par, y lo que hace como usar un Mapa para devolver un par, excepto que usted sabe que solo contiene dos valores. También está esto: https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html Si * realmente * quiere usar un par. Pero no estoy de acuerdo con que la respuesta contundente no sea útil. Debería provocar que al menos pregunte "¿Pero, por qué?". –

3

Apache Commons Lang3 proporciona una clase abstracta Pair con un par de implementaciones que incluyen ImmutablePair y MutablePair.

0

Algunos observación mía:

  1. matriz es bulit-en, rápido y fácil de usar, aunque imposible de ampliar su capacidad. ¿Qué sucede si desea que se devuelvan 3 valores después de 3 meses?

  2. ArrayList/otras colecciones pueden ser buenas, le permite aumentar la capacidad (inicialmente 10). Tenga en cuenta que Vector puede ser excesivo en comparación con ArrayList cuando solo desea almacenar 2 valores que se recuperarán más tarde. El mapa también puede ser bueno porque siempre está ordenado y ordenado.

  3. Alguna clase definida por el usuario: tal vez una opción si es significativa (significa que los datos devueltos son importantes, ish para ser un Java Bean), y desea almacenar más de 2 enteros en ella. La legibilidad es mejor en caso de que agregue más notas en su Javadoc. Puede ampliarse como desee, simplemente agregue campos en esta clase. Más lento, pero más seguro.

0

Hay una clase de pares en JavaFX, pero no debe usarla. Lo que debe utilizar es algo como esto:

// We've skipped imports and package declarations 
public final class YourClass { 
    /* Assume there is a bunch of stuff here */ 

    // I don't know what method you're using, so forgive the silly example 
    public YourClass.Pair sillyExampleOfPairs(String someString) { 
    return new YourClass.Pair(someString, someString.length() * 13); 
    } 

    @Value // Lombok annotation. 
    public static class Pair { 
    String text; 
    int integer; 
    } 

    // this is an even more succinct possibility 
    @Value public static final class ShorterPair {String text; int integer} 
} 

Mientras que el nombre de par aquí es, obviamente, no es que bien elegido, y usted debe elegir un nombre más descriptivo, las formas obvias esto va a funcionar (los campos son finales privado y usted tiene un getter en cada uno, debido a la anotación), no debe perderse en usted. Y mientras que sí, esto es un poco más prolijo que usar Pair, es mucho más robusto. ¿Qué sucede si do necesita agregar un parámetro adicional al valor de retorno? Usted "solo" necesita cambiar esta clase entonces. Y puede actualizar todos los JavaDocs relevantes inmediatamente, lo que también es bueno. Si tiene que cambiar los tipos, ambos implicarían cantidades similares de trabajo.

Mientras solo agregue cosas, los métodos getText() y getInteger() seguirían funcionando como lo hacían antes. También evitas tener que añadir Yet Another Dependency a tus proyectos. No es una gran victoria. Tener Pair disponible es bueno para prototipos, pero no es bueno para más adelante.

Mi último argumento teórico CS-y es que Pair es del mismo tipo que Pair. Pero si tiene un directorio telefónico. Ingrese (con String e int) y diga, Inventario.Elemento (con un nombre y un número de elementos que actualmente hemos inventariado), estos dos tipos son muy distintos, que hacen cosas muy distintas. No puedes poner uno en el otro. Ésto es una cosa buena.

También es mucho más claro para nosotros los bastardos pobres que tenemos que ir y depurar sus sistemas para ver algo como "com.name.project.something.something.Phonebook.Entry" en un seguimiento de pila que "org.apache.commons .lang3.tuple.Pair ". Uno de estos me dice LO QUE se supone que debo mirar, y me da información sobre POR QUÉ estoy viendo un par. El otro dice ... nada.

Ahora es posible que no te importe que tengas que escribir 3 segundos extra para ahorrarme 3 minutos. Pero elijo creer en la bondad de tu corazón y la nobleza de tu alma. Por lo tanto, haz lo correcto.

Escriba una pequeña clase estática en su lugar.

Cuestiones relacionadas