Chcę zwrócić dwa obiekty z metody Java i zastanawiałem się, jaki może być dobry sposób na zrobienie tego?
Możliwe sposoby mogę myśleć to: powrót HashMap
(od dwóch obiektów są podobne) lub zwracać ArrayList
z Object
obiektów.
Mówiąc dokładniej, dwa obiekty, które chcę zwrócić, to (a) List
obiekty i (b) ich nazwy oddzielone przecinkami.
Chcę zwrócić te dwa obiekty z jednej metody, ponieważ nie chcę iterować po liście obiektów, aby uzyskać nazwy oddzielone przecinkami (co mogę zrobić w tej samej pętli w tej metodzie).
W jakiś sposób zwrócenie HashMap
nie wygląda na zbyt elegancki sposób.
List
odniesienie i rodzaj tabeli przeglądowej.Odpowiedzi:
Jeśli chcesz zwrócić dwa obiekty, zwykle chcesz zwrócić pojedynczy obiekt, który zamiast tego hermetyzuje te dwa obiekty.
Możesz zwrócić listę
NamedObject
obiektów w następujący sposób:Następnie możesz łatwo zwrócić plik
List<NamedObject<WhateverTypeYouWant>>
.Ponadto: dlaczego chcesz zwrócić listę nazwisk rozdzielonych przecinkami zamiast znaku
List<String>
? Albo jeszcze lepiej, zwróć aMap<String,TheObjectType>
z kluczami będącymi nazwami i wartościami obiektów (chyba że twoje obiekty mają określoną kolejność, w takim przypadku aNavigableMap
może być tym, czego chcesz.źródło
Jeśli wiesz, że zwrócisz dwa obiekty, możesz również użyć pary ogólnej:
Edytuj Pełniejsza implementacja powyższego:
Uwagi, głównie na temat rustykalności w Javie i generycznych:
a
ib
są niezmienne.makePair
Metoda statyczna pomaga w pisaniu na tabliczkach kotłowych, które operator diamentu w Javie 7 uczyni mniej irytującym. Jest trochę pracy, aby zrobić to naprawdę fajne re: generics, ale teraz powinno być ok. (por. PECS)hashcode
iequals
są generowane przez zaćmienie.cast
metodzie jest w porządku, ale nie wydaje się całkiem poprawne.isInstance
są konieczne.źródło
Pair
realizacja. Jedna drobna zmiana, którą wprowadziłbym: dodaj wiadomość do plikuClassCastException
. W przeciwnym razie debugowanie stanie się koszmarem, jeśli z jakiegoś powodu to się nie powiedzie. (a rawtypes tłumić-ostrzeżenia byłoby zbędne, jeśli chcesz przesyłaćPair<?,?>
(który pracuje, bo trzeba tylkoObject
metody oda
ab
) Czy Mogę dostosować kod.?W przypadku, gdy wywoływana metoda jest prywatna lub wywoływana z jednej lokalizacji, spróbuj
Osoba dzwoniąca wygląda następująco:
Przykład pary autorstwa Davida Hanaka nie ma korzyści składniowych i jest ograniczony do dwóch wartości.
A dzwoniący wygląda następująco:
źródło
Pair<T1, T2>
,Tuple<T1, T2, T3>
,Tuple<T1, T2, T3, T4>
, Itd. Wtedy stosowanie specyficznych pokazuje liczbę i typy parametrówPair<int, String> temp = ...
czy cokolwiek innego.Możesz użyć dowolnego z następujących sposobów:
1) Korzystanie z Array
2) Korzystanie z ArrayList
3) Korzystanie z HashMap
4) Korzystanie z niestandardowej klasy kontenera
5) Korzystanie z AbstractMap.simpleEntry
6) Korzystanie z Pair of Apache Commons
źródło
Prawie zawsze kończę definiowanie klas n-Tuple, kiedy koduję w Javie. Na przykład:
Wiem, że jest trochę brzydki, ale działa i wystarczy, że raz zdefiniujesz typy krotek. Krotki to coś, czego w Javie naprawdę brakuje.
EDYCJA: przykład Davida Hanaka jest bardziej elegancki, ponieważ unika definiowania getterów i nadal utrzymuje niezmienność obiektu.
źródło
Przed Java 5 zgadzałbym się, że rozwiązanie Map nie jest idealne. Nie daje możliwości sprawdzenia typu podczas kompilacji, więc może powodować problemy w czasie wykonywania. Jednak w przypadku języka Java 5 mamy typy ogólne.
Twoja metoda mogłaby więc wyglądać następująco:
MyType jest oczywiście typem zwracanego obiektu.
Zasadniczo uważam, że zwrócenie mapy jest właściwym rozwiązaniem w tym przypadku, ponieważ jest to dokładnie to, co chcesz zwrócić - mapowanie ciągu znaków na obiekt.
źródło
Alternatywnie, w sytuacjach, w których chcę zwrócić kilka rzeczy z metody, czasami używam mechanizmu wywołania zwrotnego zamiast kontenera. Działa to bardzo dobrze w sytuacjach, w których nie mogę z góry określić, ile obiektów zostanie wygenerowanych.
W przypadku Twojego konkretnego problemu wyglądałoby to mniej więcej tak:
źródło
java
, jeśli masz obiektA
wywołania obiektuB.getResult()
iB.getResult()
wywołujeA.finishResult()
jako acallback
, czy obiektB
zbiera śmieci, czy pozostaje do zakończenia A? prawdopodobnie głupie pytanie, ale mam fundamentalne zamieszanie!Apache Commons ma do tego krotkę i potrójną:
ImmutablePair<L,R>
Niezmienna para składająca się z dwóch elementów Object.ImmutableTriple<L,M,R>
Niezmienna trójka składająca się z trzech elementów Object.MutablePair<L,R>
Zmienna para składająca się z dwóch elementów Object.MutableTriple<L,M,R>
Zmienna trójka składająca się z trzech elementów Object.Pair<L,R>
Para składająca się z dwóch elementów.Triple<L,M,R>
Trójka składająca się z trzech elementów.Źródło: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
źródło
Chociaż w twoim przypadku komentarz może być dobrym rozwiązaniem, w Androidzie możesz użyć
Pair
. Po prostuźródło
Zastosowanie następującego obiektu wpisu Przykład:
źródło
Jeśli chodzi o problem z wieloma wartościami zwracanymi, zwykle używam małej klasy pomocniczej, która opakowuje pojedynczą wartość zwracaną i jest przekazywana jako parametr do metody:
(dla prymitywnych typów danych używam niewielkich zmian, aby bezpośrednio przechowywać wartość)
Metoda, która chce zwrócić wiele wartości, zostanie wówczas zadeklarowana w następujący sposób:
Może główną wadą jest to, że wywołujący musi wcześniej przygotować zwracane obiekty na wypadek, gdyby chciał ich użyć (a metoda powinna sprawdzać wskaźniki zerowe)
Zalety (w porównaniu do innych proponowanych rozwiązań):
źródło
Wszystkie możliwe rozwiązania będą kludge (takie jak obiekty kontenerów, pomysł HashMap, „wielokrotne wartości zwracane” realizowane za pomocą tablic). Zalecam ponowne wygenerowanie listy oddzielonej przecinkami ze zwróconej listy. Kod będzie dużo czystszy.
źródło
Zachowaj prostotę i utwórz klasę dla sytuacji z wieloma wynikami. Ten przykład akceptuje ArrayList i tekst komunikatu z databasehelper getInfo.
Gdzie wywołujesz procedurę, która zwraca wiele kodowanych wartości:
W procedurze getInfo kodujesz:
i zdefiniuj klasę multResult za pomocą:
}
źródło
Jak widzę, są tu naprawdę trzy możliwości, a rozwiązanie zależy od kontekstu. Możesz zdecydować się na zaimplementowanie konstrukcji nazwy w metodzie, która tworzy listę. To jest wybór, który wybrałeś, ale nie sądzę, że jest najlepszy. Tworzysz sprzężenie w metodzie producenta z metodą konsumpcji, która nie musi istnieć. Inni dzwoniący mogą nie potrzebować dodatkowych informacji, a Ty będziesz obliczać dodatkowe informacje dla tych rozmówców.
Alternatywnie możesz użyć metody wywołującej do obliczenia nazwy. Jeśli tylko jeden dzwoniący potrzebuje tych informacji, możesz się tam zatrzymać. Nie masz żadnych dodatkowych zależności i chociaż wiąże się to z dodatkowymi obliczeniami, uniknąłeś zbyt szczegółowego tworzenia metody konstrukcji. To dobry kompromis.
Wreszcie, sama lista może być odpowiedzialna za utworzenie nazwy. To jest trasa, którą wybrałbym, gdyby obliczenia musiało być wykonane przez więcej niż jednego dzwoniącego. Myślę, że to nakłada odpowiedzialność za tworzenie nazw z klasą, która jest najbliżej spokrewniona z samymi obiektami.
W drugim przypadku moim rozwiązaniem byłoby utworzenie wyspecjalizowanej klasy List, która zwraca rozdzielony przecinkami ciąg nazw obiektów, które zawiera. Spraw, aby klasa była na tyle inteligentna, aby tworzyła ciąg z nazwą w locie, gdy obiekty są dodawane i usuwane z niego. Następnie zwróć wystąpienie tej listy i w razie potrzeby wywołaj metodę generowania nazw. Chociaż prawie tak samo efektywne (i prostsze) może być po prostu opóźnienie obliczania nazw do pierwszego wywołania metody i zapisanie jej wtedy (ładowanie z opóźnieniem). Jeśli dodasz / usuniesz obiekt, wystarczy tylko usunąć obliczoną wartość i przeliczyć ją przy następnym wywołaniu.
źródło
Potrafi coś takiego jak krotka w języku dynamicznym (Python)
i używaj w ten sposób
źródło
Zastosowałem podobne podejście niż opisane w innych odpowiedziach z kilkoma poprawkami opartymi na wymaganiu, które miałem, w zasadzie stworzyłem następujące klasy (na wszelki wypadek wszystko jest w Javie):
Wtedy moje wymaganie było proste, w klasie repozytorium, która dociera do bazy danych, dla metody Get Methods niż pobieranie danych z DB, muszę sprawdzić, czy to się nie powiodło, czy się powiedzie, a następnie, jeśli się powiedzie, musiałem pobawić się listą zwrotną , jeśli się nie powiodło, zatrzymaj wykonywanie i powiadom o błędzie.
Na przykład moje metody są takie:
Gdzie ResultMessage to po prostu klasa z dwoma polami (kod / komunikat), a Customer to dowolna klasa z zestawem pól pochodzącym z bazy danych.
Następnie, aby sprawdzić wynik, po prostu robię to:
źródło
W C ++ (STL) istnieje para klas do łączenia dwóch obiektów. W Java Generics klasa pary nie jest dostępna, chociaż jest na nią popyt . Możesz jednak łatwo wdrożyć to samodzielnie.
Zgadzam się jednak z niektórymi innymi odpowiedziami, że jeśli chcesz zwrócić dwa lub więcej obiektów z metody, lepiej byłoby zamknąć je w klasie.
źródło
Dlaczego nie utworzyć
WhateverFunctionResult
obiektu, który zawiera wyniki i logikę wymaganą do przeanalizowania tych wyników, iteracji itd. Wydaje mi się, że albo:Widzę, że ten rodzaj problemu pojawia się raz po raz. Nie bój się tworzyć własnych klas kontenerów / wyników, które zawierają dane i powiązaną z nimi funkcjonalność. Jeśli po prostu przekażesz rzeczy w
HashMap
podobny sposób, Twoi klienci będą musieli rozebrać tę mapę na części i za każdym razem, gdy chcą skorzystać z wyników, uporządkować zawartość.źródło
źródło
To nie jest dokładna odpowiedź na pytanie, ale ponieważ każde z podanych tutaj rozwiązań ma pewne wady, proponuję spróbować nieco zmienić kod, aby zwrócić tylko jedną wartość.
Przypadek pierwszy.
Potrzebujesz czegoś zarówno wewnątrz, jak i na zewnątrz swojej metody. Dlaczego nie obliczyć go na zewnątrz i przekazać do metody?
Zamiast:
Próbować:
Powinno to zaspokoić większość twoich potrzeb, ponieważ w większości sytuacji jedna wartość jest tworzona przed drugą i możesz podzielić ich tworzenie na dwie metody. Wadą jest to, że metoda
createThingsB
ma dodatkowy parametr w porównaniu docreateThings
i prawdopodobnie przekazujesz dokładnie tę samą listę parametrów dwa razy do różnych metod.Przypadek drugi.
Najbardziej oczywiste rozwiązanie w historii i uproszczona wersja przypadku pierwszego. Nie zawsze jest to możliwe, ale może obie wartości można stworzyć niezależnie od siebie?
Zamiast:
Próbować:
Aby uczynić go bardziej użytecznym, te dwie metody mogą mieć wspólną logikę:
źródło
Przekaż listę do metody i wypełnij ją, a następnie zwróć ciąg z nazwami, na przykład:
Następnie nazwij to tak:
źródło
Stosuję bardzo podstawowe podejście do rozwiązywania problemów związanych z wielokrotnymi zwrotami. Służy celowi i unika złożoności.
Nazywam to separatorem ciągów Approach
Jest skuteczny, ponieważ może nawet zwracać wartości wielu typów, np. Int, double, char, string itp
W tym podejściu wykorzystujemy ciąg, którego wystąpienie jest bardzo mało prawdopodobne. Nazywamy to separatorem. Ten separator byłby używany do oddzielania różnych wartości, gdy jest używany w funkcji
Na przykład otrzymamy nasz końcowy zwrot jako (na przykład) intValue separator doubleValue separator ... Następnie używając tego ciągu pobierzemy wszystkie wymagane informacje, które mogą być również różnych typów
Poniższy kod pokaże działanie tej koncepcji
Użyty separator to ! @ # I zwracane są 3 wartości intVal, doubleVal i stringVal
WYNIK
źródło
W C zrobiłbyś to, przekazując wskaźniki do symboli zastępczych dla wyników jako argumenty:
Spróbujmy czegoś podobnego w Javie.
źródło
PODAJ HASH DO METODY I ZALUDUJ JĄ ......
public void buildResponse (dane ciągów znaków, odpowiedź mapy);
źródło