Je souhaite renvoyer deux objets à partir d'une méthode Java et je me demandais quelle pourrait être une bonne façon de le faire?
Les moyens possibles auxquels je peux penser sont: renvoyer un HashMap
(puisque les deux objets sont liés) ou renvoyer un ArrayList
des Object
objets.
Pour être plus précis, les deux objets que je veux retourner sont (a) List
des objets et (b) des noms séparés par des virgules.
Je veux renvoyer ces deux objets à partir d'une méthode car je ne veux pas parcourir la liste des objets pour obtenir les noms séparés par des virgules (ce que je peux faire dans la même boucle dans cette méthode).
D'une manière ou d'une autre, renvoyer un HashMap
ne semble pas être une manière très élégante de le faire.
List
référence et une sorte de table de recherche.Réponses:
Si vous souhaitez renvoyer deux objets, vous souhaitez généralement renvoyer un seul objet qui encapsule les deux objets à la place.
Vous pouvez renvoyer une liste d'
NamedObject
objets comme ceci:Ensuite, vous pouvez facilement retourner un fichier
List<NamedObject<WhateverTypeYouWant>>
.Aussi: Pourquoi voudriez-vous renvoyer une liste de noms séparés par des virgules au lieu d'un
List<String>
? Ou mieux encore, retournez aMap<String,TheObjectType>
avec les clés étant les noms et les valeurs des objets (sauf si vos objets ont spécifié un ordre, auquel cas aNavigableMap
peut être ce que vous voulez.la source
Si vous savez que vous allez renvoyer deux objets, vous pouvez également utiliser une paire générique:
Edit Une implémentation plus complète de ce qui précède:
Remarques, principalement sur la rouille avec Java et les génériques:
a
etb
sont immuables.makePair
La méthode statique vous aide à saisir la plaque de chaudière, ce que l'opérateur diamant de Java 7 rendra moins ennuyeux. Il y a du travail pour rendre ce re: génériques vraiment sympa, mais ça devrait être ok-ish maintenant. (cf PECS)hashcode
etequals
sont générés par éclipse.cast
méthode est correct, mais ne semble pas tout à fait correct.isInstance
soient nécessaires.la source
Pair
implémentation. Un changement mineur que je ferais: ajouter un message auClassCastException
. Sinon, le débogage devient un cauchemar si cela échoue pour une raison quelconque. (et les rawtypes suppress-warnings seraient inutiles si vous faisiez un cast versPair<?,?>
(ce qui fonctionne, car vous n'avez besoin que deObject
méthodes dea
etb
). Cela vous dérange-t-il si je modifie le code?Dans le cas où la méthode que vous appelez est privée ou appelée à partir d'un emplacement, essayez
L'appelant ressemble à:
L'exemple Pair de David Hanak n'a aucun avantage syntaxique et est limité à deux valeurs.
Et l'appelant ressemble à:
la source
Pair<T1, T2>
,Tuple<T1, T2, T3>
,Tuple<T1, T2, T3, T4>
, Etc. Ensuite , une utilisation spécifique indique le nombre et les types de paramètresPair<int, String> temp = ...
ou autre chose.Vous pouvez utiliser l'une des méthodes suivantes:
1) Utilisation de la matrice
2) Utilisation de ArrayList
3) Utilisation de HashMap
4) Utilisation de votre classe de conteneur personnalisée
5) Utilisation de AbstractMap.simpleEntry
6) Utilisation d'une paire d' Apache Commons
la source
Je finis presque toujours par définir des classes n-Tuple lorsque je code en Java. Par exemple:
Je sais que c'est un peu moche, mais cela fonctionne, et il vous suffit de définir vos types de tuple une fois. Les tuples sont quelque chose qui manque vraiment à Java.
EDIT: L'exemple de David Hanak est plus élégant, car il évite de définir des getters et garde toujours l'objet immuable.
la source
Avant Java 5, je conviendrais en quelque sorte que la solution Map n'est pas idéale. Cela ne vous donnerait pas la vérification du type au moment de la compilation et pourrait donc causer des problèmes lors de l'exécution. Cependant, avec Java 5, nous avons des types génériques.
Votre méthode pourrait donc ressembler à ceci:
MyType étant bien sûr le type d'objet que vous renvoyez.
Fondamentalement, je pense que renvoyer une carte est la bonne solution dans ce cas, car c'est exactement ce que vous voulez retourner - un mappage d'une chaîne sur un objet.
la source
Alternativement, dans les situations où je veux retourner un certain nombre de choses à partir d'une méthode, j'utiliserai parfois un mécanisme de rappel au lieu d'un conteneur. Cela fonctionne très bien dans les situations où je ne peux pas spécifier à l'avance combien d'objets seront générés.
Avec votre problème particulier, cela ressemblerait à ceci:
la source
java
, si vous avez un objet d'A
appel d'objetB.getResult()
et desB.getResult()
appels enA.finishResult()
tant quecallback
, l'objetB
est-il ramassé ou reste-t-il jusqu'à ce que A se termine? probablement une question stupide mais c'est une confusion fondamentale que j'ai!Apache Commons a un tuple et un triple pour cela:
ImmutablePair<L,R>
Une paire immuable composée de deux éléments Object.ImmutableTriple<L,M,R>
Un triple immuable composé de trois éléments Object.MutablePair<L,R>
Une paire mutable composée de deux éléments Object.MutableTriple<L,M,R>
Un triple mutable composé de trois éléments Object.Pair<L,R>
Une paire composée de deux éléments.Triple<L,M,R>
Un triple composé de trois éléments.Source: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
la source
Alors que dans votre cas, le commentaire peut être un bon moyen de procéder, sous Android, vous pouvez l'utiliser
Pair
. Simplementla source
Utilisation de l'objet Entry suivant Exemple:
la source
En ce qui concerne le problème des valeurs de retour multiples en général, j'utilise généralement une petite classe d'assistance qui encapsule une seule valeur de retour et est passée en paramètre à la méthode:
(pour les types de données primitifs, j'utilise des variations mineures pour stocker directement la valeur)
Une méthode qui veut retourner plusieurs valeurs serait alors déclarée comme suit:
Peut-être que le principal inconvénient est que l'appelant doit préparer les objets de retour à l'avance au cas où il voudrait les utiliser (et la méthode devrait vérifier les pointeurs nuls)
Avantages (par rapport aux autres solutions proposées):
la source
Toutes les solutions possibles seront un kludge (comme les objets conteneurs, votre idée HashMap, «plusieurs valeurs de retour» telles que réalisées via des tableaux). Je recommande de régénérer la liste séparée par des virgules de la liste retournée. Le code finira par être beaucoup plus propre.
la source
Restez simple et créez une classe pour une situation à résultats multiples. Cet exemple accepte une ArrayList et un texte de message à partir d'un databasehelper getInfo.
Où vous appelez la routine qui renvoie plusieurs valeurs que vous codez:
Dans la routine getInfo vous codez:
et définissez une classe multResult avec:
}
la source
Selon moi, il y a vraiment trois choix ici et la solution dépend du contexte. Vous pouvez choisir d'implémenter la construction du nom dans la méthode qui produit la liste. C'est le choix que vous avez choisi, mais je ne pense pas que ce soit le meilleur. Vous créez un couplage dans la méthode du producteur avec la méthode de consommation qui n'a pas besoin d'exister. D'autres appelants peuvent ne pas avoir besoin des informations supplémentaires et vous calculeriez des informations supplémentaires pour ces appelants.
Vous pouvez également demander à la méthode appelante de calculer le nom. Si un seul appelant a besoin de ces informations, vous pouvez vous arrêter là. Vous n'avez pas de dépendances supplémentaires et bien qu'il y ait un petit calcul supplémentaire impliqué, vous avez évité de rendre votre méthode de construction trop spécifique. C'est un bon compromis.
Enfin, vous pourriez avoir la liste elle-même responsable de la création du nom. C'est l'itinéraire que j'irais si le calcul doit être effectué par plus d'un appelant. Je pense que cela confère la responsabilité de la création des noms à la classe la plus étroitement liée aux objets eux-mêmes.
Dans ce dernier cas, ma solution serait de créer une classe List spécialisée qui renvoie une chaîne séparée par des virgules des noms des objets qu'elle contient. Rendez la classe suffisamment intelligente pour qu'elle construise la chaîne de nom à la volée au fur et à mesure que des objets y sont ajoutés et supprimés. Ensuite, retournez une instance de cette liste et appelez la méthode de génération de nom si nécessaire. Bien qu'il puisse être presque aussi efficace (et plus simple) de simplement retarder le calcul des noms jusqu'au premier appel de la méthode et de le stocker ensuite (chargement différé). Si vous ajoutez / supprimez un objet, il vous suffit de supprimer la valeur calculée et de la recalculer lors du prochain appel.
la source
Peut faire quelque chose comme un tuple en langage dynamique (Python)
et utiliser comme ça
la source
J'ai suivi une approche similaire à celle décrite dans les autres réponses avec quelques ajustements basés sur l'exigence que j'avais, en gros, j'ai créé les classes suivantes (juste au cas où, tout est Java):
Ensuite, mon exigence était simple, dans la classe de référentiel qui atteint la base de données, pour les méthodes Get que de récupérer des données de la base de données, je dois vérifier si cela a échoué ou réussi, puis, en cas de succès, je devais jouer avec la liste de retour , en cas d'échec, arrêtez l'exécution et notifiez l'erreur.
Ainsi, par exemple, mes méthodes sont comme ceci:
Où ResultMessage est juste une classe avec deux champs (code / message) et Customer est n'importe quelle classe avec un tas de champs provenant de la base de données.
Ensuite, pour vérifier le résultat, je fais juste ceci:
la source
En C ++ (STL), il existe une classe de paires pour regrouper deux objets. Dans Java Generics, une classe de paires n'est pas disponible, bien qu'il y ait une certaine demande . Cependant, vous pouvez facilement l'implémenter vous-même.
Je suis cependant d'accord avec certaines autres réponses que si vous devez renvoyer deux objets ou plus à partir d'une méthode, il serait préférable de les encapsuler dans une classe.
la source
Pourquoi ne pas créer un
WhateverFunctionResult
objet contenant vos résultats, et la logique nécessaire pour analyser ces résultats, itérer ensuite etc. Il me semble que soit:Je vois ce genre de problème surgir encore et encore. N'ayez pas peur de créer vos propres classes de conteneur / résultat contenant les données et les fonctionnalités associées pour gérer cela. Si vous faites simplement passer les choses dans un
HashMap
ou similaire, vos clients doivent séparer cette carte et en groover le contenu chaque fois qu'ils veulent utiliser les résultats.la source
la source
Cela ne répond pas exactement à la question, mais comme chacune des solutions présentées ici présente des inconvénients, je suggère d'essayer de refactoriser un peu votre code afin que vous n'ayez à renvoyer qu'une seule valeur.
Cas un.
Vous avez besoin de quelque chose à l'intérieur comme à l'extérieur de votre méthode. Pourquoi ne pas le calculer à l'extérieur et le passer à la méthode?
Au lieu de:
Essayer:
Cela devrait couvrir la plupart de vos besoins, car dans la plupart des situations, une valeur est créée avant l'autre et vous pouvez les séparer en deux méthodes. L'inconvénient est que la méthode
createThingsB
a un paramètre supplémentaire par rapport àcreateThings
, et peut-être que vous passez exactement la même liste de paramètres deux fois à différentes méthodes.Cas deux.
La solution la plus évidente jamais réalisée et une version simplifiée du cas un. Ce n'est pas toujours possible, mais peut-être que les deux valeurs peuvent être créées indépendamment l'une de l'autre?
Au lieu de:
Essayer:
Pour le rendre plus utile, ces deux méthodes peuvent partager une logique commune:
la source
Passez une liste à votre méthode et remplissez-la, puis renvoyez la chaîne avec les noms, comme ceci:
Alors appelez-le comme ceci:
la source
J'ai utilisé une approche très basique pour traiter les problèmes de retours multiples. Cela sert le but et évite la complexité.
Je l'appelle l' approche du séparateur de chaîne
Et il est efficace car il peut même renvoyer des valeurs de plusieurs types par exemple int, double, char, string, etc.
Dans cette approche, nous utilisons une chaîne qui est très peu susceptible de se produire en général. Nous l'appelons comme un séparateur. Ce séparateur serait utilisé pour séparer diverses valeurs lorsqu'il est utilisé dans une fonction
Par exemple, nous aurons notre retour final comme (par exemple) intValue separator doubleValue separator ... Et puis en utilisant cette chaîne, nous récupérerons toutes les informations nécessaires, qui peuvent également être de types différents
Le code suivant montrera le fonctionnement de ce concept
Le séparateur utilisé est ! @ # Et 3 valeurs sont renvoyées intVal, doubleVal et stringVal
PRODUCTION
la source
En C, vous le feriez en passant des pointeurs vers des espaces réservés pour les résultats sous forme d'arguments:
Essayons quelque chose de similaire, en Java.
la source
PASSER UN HASH À LA MÉTHODE ET LA POPULER ......
public void buildResponse (données de chaîne, réponse de carte);
la source