Quiero devolver dos objetos de un método Java y me preguntaba cuál podría ser una buena manera de hacerlo.
Las posibles formas en las que puedo pensar son: devolver a HashMap
(ya que los dos Objetos están relacionados) o devolver un ArrayList
de Object
objetos.
Para ser más precisos, los dos objetos que quiero devolver son (a) List
de objetos y (b) nombres separados por comas de los mismos.
Quiero devolver estos dos objetos de un método porque no quiero recorrer la lista de objetos para obtener los nombres separados por comas (lo que puedo hacer en el mismo bucle en este método).
De alguna manera, devolver un HashMap
no parece una forma muy elegante de hacerlo.
List
referencia única y una especie de tabla de búsqueda.Respuestas:
Si desea devolver dos objetos, generalmente desea devolver un solo objeto que encapsule los dos objetos.
Puede devolver una lista de
NamedObject
objetos como este:Entonces puede devolver fácilmente a
List<NamedObject<WhateverTypeYouWant>>
.Además: ¿por qué querría devolver una lista de nombres separados por comas en lugar de a
List<String>
? O mejor aún, devuelva unMap<String,TheObjectType>
con las claves que son los nombres y los valores de los objetos (a menos que sus objetos tengan un orden específico, en cuyo casoNavigableMap
podría ser lo que desea.fuente
Si sabe que va a devolver dos objetos, también puede usar un par genérico:
Editar Una implementación más completa de lo anterior:
Notas, principalmente sobre la oxidación con Java y genéricos:
a
yb
son inmutables.makePair
El método estático lo ayuda a escribir la placa de la caldera, lo que el operador de diamantes en Java 7 hará menos molesto. Hay algo de trabajo para hacer que este re: genéricos sea realmente agradable, pero ahora debería estar bien. (cf PECS)hashcode
yequals
son generados por eclipse.cast
método está bien, pero no parece ser correcto.isInstance
son necesarios.fuente
Pair
implementación. Un cambio menor que haría: agregar un mensaje alClassCastException
. De lo contrario, la depuración se convierte en una pesadilla si esto falla por alguna razón. (y las advertencias de supresión de los tipos sin formato serían innecesarias si se realiza la conversiónPair<?,?>
(lo que funciona, porque solo necesitaObject
métodos dea
yb
). ¿Le importa si modifico el código?En el caso de que el método al que llama sea privado o se llame desde una ubicación, intente
La persona que llama se ve así:
El ejemplo Pair de David Hanak no tiene beneficio sintáctico y está limitado a dos valores.
Y la persona que llama se ve así:
fuente
Pair<T1, T2>
,Tuple<T1, T2, T3>
,Tuple<T1, T2, T3, T4>
, Etc. A continuación, un uso shows específicos del número y tipos de parámetrosPair<int, String> temp = ...
o lo que sea.Puede usar cualquiera de las siguientes formas:
1) Usando Array
2) Usando ArrayList
3) Usando HashMap
4) Usando su clase de contenedor personalizado
5) Usando AbstractMap.simpleEntry
6) Usando Par de Apache Commons
fuente
Casi siempre termino definiendo clases n-Tuple cuando codifico en Java. Por ejemplo:
Sé que es un poco feo, pero funciona, y solo tienes que definir tus tipos de tuplas una vez. Las tuplas son algo que Java realmente carece.
EDITAR: el ejemplo de David Hanak es más elegante, ya que evita definir getters y aún mantiene el objeto inmutable.
fuente
Antes de Java 5, estaría de acuerdo en que la solución Map no es ideal. No le daría una verificación de tipo de tiempo de compilación, por lo que puede causar problemas en tiempo de ejecución. Sin embargo, con Java 5, tenemos tipos genéricos.
Entonces su método podría verse así:
MyType, por supuesto, es el tipo de objeto que está devolviendo.
Básicamente, creo que devolver un Mapa es la solución correcta en este caso porque eso es exactamente lo que desea devolver: una asignación de una cadena a un objeto.
fuente
Alternativamente, en situaciones en las que quiero devolver varias cosas de un método, a veces usaré un mecanismo de devolución de llamada en lugar de un contenedor. Esto funciona muy bien en situaciones en las que no puedo especificar con anticipación cuántos objetos se generarán.
Con su problema particular, se vería así:
fuente
java
, si tiene objetoA
llamado objetoB.getResult()
yB.getResult()
llamadasA.finishResult()
como acallback
, ¿el objetoB
se recolecta basura o permanece ahí hasta que A termine? ¡Probablemente sea una pregunta estúpida pero es una confusión fundamental que tengo!Apache Commons tiene tuplas y triples para esto:
ImmutablePair<L,R>
Un par inmutable que consta de dos elementos Object.ImmutableTriple<L,M,R>
Un triple inmutable que consta de tres elementos Object.MutablePair<L,R>
Un par mutable que consta de dos elementos Object.MutableTriple<L,M,R>
Un triple mutable que consta de tres elementos Object.Pair<L,R>
Un par que consta de dos elementos.Triple<L,M,R>
Un triple que consta de tres elementos.Fuente: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
fuente
Mientras que en su caso, el comentario puede ser una buena manera de hacerlo, en Android, puede usarlo
Pair
. Simplementefuente
Uso del siguiente objeto de entrada Ejemplo:
fuente
Con respecto al problema sobre los valores de retorno múltiples en general, generalmente uso una pequeña clase auxiliar que envuelve un solo valor de retorno y se pasa como parámetro al método:
(para los tipos de datos primitivos utilizo variaciones menores para almacenar directamente el valor)
Un método que quiera devolver múltiples valores se declararía de la siguiente manera:
Tal vez el principal inconveniente es que la persona que llama tiene que preparar los objetos devueltos por adelantado en caso de que quiera usarlos (y el método debe verificar si hay punteros nulos)
Ventajas (en comparación con otras soluciones propuestas):
fuente
Todas las posibles soluciones serán un kludge (como objetos de contenedor, su idea de HashMap, "valores de retorno múltiples" realizados a través de matrices). Recomiendo regenerar la lista separada por comas de la Lista devuelta. El código terminará siendo mucho más limpio.
fuente
Manténgalo simple y cree una clase para situaciones de resultados múltiples. Este ejemplo acepta una ArrayList y un mensaje de texto de una base de datos de ayuda getInfo.
Donde llama a la rutina que devuelve múltiples valores que codifica:
En la rutina getInfo usted codifica:
y defina una clase multResult con:
}
fuente
Desde mi punto de vista, hay realmente tres opciones aquí y la solución depende del contexto. Puede optar por implementar la construcción del nombre en el método que produce la lista. Esta es la elección que has elegido, pero no creo que sea la mejor. Está creando un acoplamiento en el método del productor con el método de consumo que no necesita existir. Es posible que otras personas que llaman no necesiten la información adicional y usted estaría calculando información adicional para estas personas que llaman.
Alternativamente, puede hacer que el método de llamada calcule el nombre. Si solo hay una persona que llama que necesita esta información, puede detenerse allí. No tiene dependencias adicionales y, aunque hay un pequeño cálculo adicional involucrado, ha evitado que su método de construcción sea demasiado específico. Esta es una buena compensación.
Por último, puede hacer que la lista misma sea responsable de crear el nombre. Esta es la ruta que seguiría si el cálculo debe ser realizado por más de una persona que llama. Creo que esto pone la responsabilidad de la creación de los nombres con la clase que está más estrechamente relacionada con los objetos mismos.
En el último caso, mi solución sería crear una clase de Lista especializada que devuelva una cadena separada por comas de los nombres de los objetos que contiene. Haga que la clase sea lo suficientemente inteligente como para que construya la cadena de nombre sobre la marcha a medida que se agregan y eliminan objetos. Luego, devuelva una instancia de esta lista y llame al método de generación de nombres según sea necesario. Aunque puede ser casi tan eficiente (y más simple) simplemente retrasar el cálculo de los nombres hasta la primera vez que se llama al método y almacenarlo luego (carga diferida). Si agrega / elimina un objeto, solo necesita eliminar el valor calculado y hacer que se vuelva a calcular en la próxima llamada.
fuente
Puede hacer algo como una tupla en lenguaje dinámico (Python)
y usar así
fuente
Seguí un enfoque similar al descrito en las otras respuestas con algunos ajustes basados en el requisito que tenía, básicamente creé las siguientes clases (por si acaso, todo es Java):
Entonces, mi requisito era simple, en la clase de repositorio que llega a la base de datos, para obtener métodos que recuperar datos de la base de datos, necesito verificar si falló o tuvo éxito, luego, si tenía éxito, necesitaba jugar con la lista de retorno , si falla, detenga la ejecución y notifique el error.
Entonces, por ejemplo, mis métodos son así:
Donde ResultMessage es solo una clase con dos campos (código / mensaje) y Customer es cualquier clase con un montón de campos que provienen de la base de datos.
Luego, para verificar el resultado, solo hago esto:
fuente
En C ++ (STL) hay una clase de pares para agrupar dos objetos. En Java Generics, una clase de pares no está disponible, aunque existe cierta demanda . Sin embargo, podría implementarlo usted mismo fácilmente.
Sin embargo, estoy de acuerdo con algunas otras respuestas que si necesita devolver dos o más objetos de un método, sería mejor encapsularlos en una clase.
fuente
¿Por qué no crear un
WhateverFunctionResult
objeto que contenga sus resultados y la lógica necesaria para analizar estos resultados, repetirlos, etc.? Me parece que tampoco:Veo este tipo de problemas surgir una y otra vez. No tenga miedo de crear sus propias clases de contenedor / resultado que contengan los datos y la funcionalidad asociada para manejar esto. Si simplemente pasa las cosas en una
HashMap
o similar, entonces sus clientes tienen que separar este mapa y asimilar el contenido cada vez que quieran usar los resultados.fuente
fuente
Esto no responde exactamente la pregunta, pero dado que cada una de las soluciones dadas aquí tiene algunos inconvenientes, le sugiero que intente refactorizar su código un poco, por lo que debe devolver solo un valor.
Caso uno.
Necesita algo dentro y fuera de su método. ¿Por qué no calcularlo afuera y pasarlo al método?
En vez de:
Tratar:
Esto debería cubrir la mayoría de sus necesidades, ya que en la mayoría de las situaciones se crea un valor antes que el otro y puede dividirlo creando dos métodos. El inconveniente es que el método
createThingsB
tiene un parámetro adicional en comparacióncreateThings
, y posiblemente esté pasando exactamente la misma lista de parámetros dos veces a diferentes métodos.Caso dos.
La solución más obvia y una versión simplificada del caso uno. No siempre es posible, pero ¿quizás ambos valores se puedan crear independientemente uno del otro?
En vez de:
Tratar:
Para hacerlo más útil, estos dos métodos pueden compartir una lógica común:
fuente
Pase una lista a su método y complétela, luego devuelva la Cadena con los nombres, así:
Entonces llámalo así:
fuente
He estado usando un enfoque muy básico para lidiar con problemas de retornos múltiples. Cumple el propósito y evita la complejidad.
Lo llamo el enfoque separador de cadenas
Y es eficaz, ya que incluso puede devolver valores de tipos múltiples, por ejemplo, int, double, char, string, etc.
En este enfoque, usamos una cadena que es muy poco probable que ocurra en general. Lo llamamos como un separador. Este separador se usaría para separar varios valores cuando se usa en una función
Por ejemplo, tendremos nuestro retorno final como (por ejemplo) separador intValue separador doubleValue ... Y luego, usando esta cadena, recuperaremos toda la información requerida, que también puede ser de diferentes tipos.
El siguiente código mostrará el funcionamiento de este concepto.
El separador utilizado es ! @ # Y se devuelven 3 valores intVal, doubleVal y stringVal
SALIDA
fuente
En C, lo haría pasando punteros a marcadores de posición para los resultados como argumentos:
Probemos algo similar, en Java.
fuente
PASAR UN HASH EN EL MÉTODO Y POBLARLO ......
public Void buildResponse (datos de cadena, respuesta de mapa);
fuente