Eu quero retornar dois objetos de um método Java e fiquei pensando o que poderia ser uma boa maneira de fazer isso?
As possíveis maneiras em que posso pensar são: retornar a HashMap
( uma vez que os dois objetos estão relacionados) ou retornar um ArrayList
dos Object
objetos.
Para ser mais preciso, os dois objetos que quero retornar são (a) List
de objetos e (b) nomes separados por vírgula.
Eu quero retornar esses dois objetos de um método porque não quero percorrer a lista de objetos para obter os nomes separados por vírgula (o que posso fazer no mesmo loop neste método).
De alguma forma, retornar a HashMap
não parece uma maneira muito elegante de fazê-lo.
List
referência e uma espécie de tabela de pesquisa.Respostas:
Se você deseja retornar dois objetos, geralmente deseja retornar um único objeto que encapsule os dois objetos.
Você pode retornar uma lista de
NamedObject
objetos como este:Então você pode facilmente retornar um
List<NamedObject<WhateverTypeYouWant>>
.Além disso: Por que você deseja retornar uma lista de nomes separados por vírgula em vez de a
List<String>
? Ou melhor ainda, retorne aMap<String,TheObjectType>
com as chaves sendo os nomes e os valores dos objetos (a menos que seus objetos tenham especificado a ordem, nesse caso, aNavigableMap
pode ser o que você deseja.fonte
Se você sabe que retornará dois objetos, também poderá usar um par genérico:
Editar Uma implementação mais completa do acima:
Observações, principalmente sobre a oxidação com Java e genéricos:
a
eb
são imutáveis.makePair
O método estático ajuda na digitação da placa da caldeira, que o operador de diamante no Java 7 tornará menos irritante. Há algum trabalho para tornar esta re: genéricos realmente agradável, mas deve estar ok agora. (cf. PECS)hashcode
eequals
são gerados pelo eclipse.cast
método está correta, mas não parece correta.isInstance
são necessários.fonte
Pair
implementação muito boa . Uma pequena alteração que eu faria: adicione uma mensagem aoClassCastException
. Caso contrário, a depuração se tornará um pesadelo se isso falhar por algum motivo. (e os rawtypes suprimir-avisos seria desnecessário se você tivesse convertido paraPair<?,?>
(que funciona, porque você só precisa deObject
métodos dea
eb
) Você se importa se eu ajustar o código.?Caso o método que você está chamando seja privado ou chamado de um local, tente
O chamador se parece com:
O exemplo do par de David Hanak não tem benefício sintático e é limitado a dois valores.
E o chamador se parece com:
fonte
Pair<T1, T2>
,Tuple<T1, T2, T3>
,Tuple<T1, T2, T3, T4>
, Etc. Em seguida, uma específicas de uso mostra o número e tipos de parâmetrosPair<int, String> temp = ...
ou o que quer.Você pode usar qualquer uma das seguintes maneiras:
1) Usando matriz
2) Usando ArrayList
3) Usando o HashMap
4) Usando sua classe de contêiner personalizado
5) Usando AbstractMap.simpleEntry
6) Usando o Par de Apache Commons
fonte
Quase sempre acabo definindo classes n-Tuple quando codifico em Java. Por exemplo:
Eu sei que é um pouco feio, mas funciona, e você só precisa definir seus tipos de tupla uma vez. Tuplas são algo que realmente falta ao Java.
EDIT: O exemplo de David Hanak é mais elegante, pois evita definir getters e ainda mantém o objeto imutável.
fonte
Antes do Java 5, eu meio que concordava que a solução Map não é ideal. Isso não forneceria a verificação do tipo de tempo de compilação, o que pode causar problemas em tempo de execução. No entanto, com o Java 5, temos tipos genéricos.
Portanto, seu método pode ficar assim:
MyType, é claro, o tipo de objeto que você está retornando.
Basicamente, acho que retornar um mapa é a solução certa nesse caso, porque é exatamente isso que você deseja retornar - um mapeamento de uma string para um objeto.
fonte
Como alternativa, nas situações em que desejo retornar várias coisas de um método, algumas vezes utilizarei um mecanismo de retorno de chamada em vez de um contêiner. Isso funciona muito bem em situações em que não posso especificar antecipadamente quantos objetos serão gerados.
Com o seu problema específico, seria algo como isto:
fonte
java
, se você tiver um objetoA
chamado objetoB.getResult()
eB.getResult()
chamaA.finishResult()
como acallback
, o objetoB
é coletado como lixo ou fica por lá até que A termine? provavelmente uma pergunta estúpida, mas é uma confusão fundamental que eu tenho!O Apache Commons possui tupla e tripla para isso:
ImmutablePair<L,R>
Um par imutável que consiste em dois elementos Objeto.ImmutableTriple<L,M,R>
Um triplo imutável que consiste em três elementos Objeto.MutablePair<L,R>
Um par mutável que consiste em dois elementos Objeto.MutableTriple<L,M,R>
Um triplo mutável que consiste em três elementos Objeto.Pair<L,R>
Um par que consiste em dois elementos.Triple<L,M,R>
Um triplo composto por três elementos.Fonte: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
fonte
Enquanto no seu caso, o comentário pode ser um bom caminho, no Android, você pode usar
Pair
. Simplesmentefonte
Uso do seguinte objeto de Entrada Exemplo:
fonte
Em relação à questão sobre vários valores de retorno em geral, geralmente uso uma classe auxiliar pequena que agrupa um único valor de retorno e é passada como parâmetro para o método:
(para tipos de dados primitivos, utilizo pequenas variações para armazenar diretamente o valor)
Um método que deseja retornar vários valores seria declarado da seguinte maneira:
Talvez a principal desvantagem seja que o chamador precisa preparar os objetos de retorno antecipadamente, caso queira usá-los (e o método deve verificar se há indicadores nulos)
Vantagens (em comparação com outras soluções propostas):
fonte
Todas as soluções possíveis serão um kludge (como objetos de contêiner, sua ideia do HashMap, "múltiplos valores de retorno", conforme realizado por meio de matrizes). Eu recomendo regenerar a lista separada por vírgulas da lista retornada. O código acabará sendo muito mais limpo.
fonte
Mantenha-o simples e crie uma classe para situações com vários resultados. Este exemplo aceita um ArrayList e um texto de mensagem de um databasehelper getInfo.
Onde você chama a rotina que retorna vários valores que você codifica:
Na rotina getInfo, você codifica:
e defina uma classe multResult com:
}
fonte
A meu ver, existem realmente três opções aqui e a solução depende do contexto. Você pode optar por implementar a construção do nome no método que produz a lista. Essa é a escolha que você escolheu, mas não acho que seja a melhor. Você está criando um acoplamento no método produtor ao método de consumo que não precisa existir. Outros chamadores podem não precisar de informações adicionais e você calcularia informações adicionais para esses chamadores.
Como alternativa, você pode fazer com que o método de chamada calcule o nome. Se houver apenas um chamador que precise dessas informações, você poderá parar por aí. Você não tem dependências extras e, embora exista um pouco de cálculo extra, evitou tornar seu método de construção muito específico. Este é um bom compromisso.
Por fim, a própria lista pode ser responsável por criar o nome. Esta é a rota que eu seguiria se o cálculo precisasse ser feito por mais de um chamador. Eu acho que isso coloca a responsabilidade pela criação dos nomes com a classe que está mais intimamente relacionada aos próprios objetos.
No último caso, minha solução seria criar uma classe List especializada que retorne uma string separada por vírgula dos nomes dos objetos que ela contém. Torne a classe inteligente o suficiente para que ela construa a string de nome rapidamente, à medida que objetos são adicionados e removidos dela. Em seguida, retorne uma instância desta lista e chame o método de geração de nomes conforme necessário. Embora possa ser quase tão eficiente (e mais simples) simplesmente atrasar o cálculo dos nomes até a primeira vez que o método é chamado e armazená-lo (carregamento lento). Se você adicionar / remover um objeto, precisará remover apenas o valor calculado e recalculá-lo na próxima chamada.
fonte
Pode fazer algo como uma tupla em linguagem dinâmica (Python)
e use assim
fonte
Eu segui uma abordagem semelhante à descrita nas outras respostas com alguns ajustes com base no requisito que eu tinha, basicamente criei as seguintes classes (apenas no caso, tudo é Java):
Então, meu requisito era simples, na classe do repositório que alcança o banco de dados, para os métodos Get que recuperam dados do banco de dados, preciso verificar se ele falhou ou teve êxito, se tiver êxito, eu precisava brincar com a lista de retorno , se falhar, pare a execução e notifique o erro.
Então, por exemplo, meus métodos são assim:
Onde ResultMessage é apenas uma classe com dois campos (código / mensagem) e Customer é qualquer classe com vários campos provenientes do banco de dados.
Então, para verificar o resultado, basta fazer o seguinte:
fonte
No C ++ (STL), há uma classe de pares para agrupar dois objetos. Em Java Generics, uma classe de pares não está disponível, embora exista alguma demanda por ela. Você pode facilmente implementá-lo você mesmo.
No entanto, concordo com algumas outras respostas: se você precisar retornar dois ou mais objetos de um método, seria melhor encapsulá-los em uma classe.
fonte
Por que não criar um
WhateverFunctionResult
objeto que contenha seus resultados e a lógica necessária para analisá-los, iterar nesse momento etc. Parece-me que:Vejo esse tipo de problema surgir várias vezes. Não tenha medo de criar suas próprias classes de contêiner / resultado que contêm os dados e a funcionalidade associada para lidar com isso. Se você simplesmente distribuir o material em um
HashMap
ou similar, seus clientes terão que separar esse mapa e separar o conteúdo toda vez que quiserem usar os resultados.fonte
fonte
Isso não está respondendo exatamente à pergunta, mas como todas as soluções fornecidas aqui têm algumas desvantagens, sugiro tentar refatorar seu código um pouco para que você precise retornar apenas um valor.
Caso um.
Você precisa de algo dentro e fora do seu método. Por que não calculá-lo fora e passá-lo para o método?
Ao invés de:
Experimentar:
Isso deve cobrir a maioria das suas necessidades, pois na maioria das situações um valor é criado antes do outro e você pode dividir a criação em dois métodos. A desvantagem é que o método
createThingsB
possui um parâmetro extra em comparação comcreateThings
, e possivelmente você está passando exatamente a mesma lista de parâmetros duas vezes para métodos diferentes.Caso dois.
Solução mais óbvia de todos os tempos e uma versão simplificada do caso um. Nem sempre é possível, mas talvez os dois valores possam ser criados independentemente um do outro?
Ao invés de:
Experimentar:
Para torná-lo mais útil, esses dois métodos podem compartilhar uma lógica comum:
fonte
Passe uma lista para o seu método e preencha-a, depois retorne a String com os nomes, assim:
Então chame assim:
fonte
Eu tenho usado uma abordagem muito básica para lidar com problemas de retornos múltiplos. Ele serve ao propósito e evita a complexidade.
Eu chamo-lhe a corda separador Approach
E é eficaz, pois pode até retornar valores de Vários Tipos, por exemplo, int, double, char, string etc.
Nesta abordagem, usamos uma string que é muito improvável que ocorra geralmente. Chamamos isso de separador. Esse separador seria usado para separar vários valores quando usado em uma função
Por exemplo, teremos nosso retorno final como (por exemplo) separador intValue separador doubleValue ... E, usando essa string, recuperaremos todas as informações necessárias, que também podem ser de tipos diferentes
O código a seguir mostrará o funcionamento desse conceito
O separador usado é ! @ # E 3 valores estão sendo retornados intVal, doubleVal e stringVal
RESULTADO
fonte
Em C, você faria isso passando ponteiros para espaços reservados para os resultados como argumentos:
Vamos tentar algo semelhante, em Java.
fonte
PASSE UM HASH PARA O MÉTODO E POPULUE-O ......
public void buildResponse (dados da string, resposta do mapa);
fonte