Czy istnieje dobry powód, dla którego nie ma Pair<L,R>
Java? Jaki byłby odpowiednik tego konstruktu C ++? Wolałbym raczej nie wdrożyć własnego.
Wydaje się, że 1.6 zapewnia coś podobnego ( AbstractMap.SimpleEntry<K,V>
), ale wygląda to na dość skomplikowane.
AbstractMap.SimpleEntry
zawiłe?Odpowiedzi:
W wątku
comp.lang.java.help
Hunter Gratzner podaje kilka argumentów przeciwko obecnościPair
konstruktu w Javie. Głównym argumentem jest to, że klasaPair
nie przekazuje żadnej semantyki na temat relacji między tymi dwiema wartościami (skąd wiesz, co oznaczają „pierwsze” i „drugie”?).Lepszą praktyką jest napisanie bardzo prostej klasy, takiej jak ta zaproponowana przez Mike'a, dla każdej aplikacji, którą zrobiłbyś z tej
Pair
klasy.Map.Entry
jest przykładem pary, która ma swoje znaczenie w nazwie.Podsumowując, moim zdaniem lepiej jest mieć klasę
Position(x,y)
, klasęRange(begin,end)
i klasęEntry(key,value)
niż rodzajowąPair(first,second)
, która nie mówi mi nic o tym, co powinna zrobić.źródło
To jest Java. Musisz stworzyć własną, dopasowaną klasę Pair z opisowymi nazwami klas i pól, i nie wspominając o tym, że wymyślisz koło ponownie, pisząc hashCode () / equals () lub wdrażając Porównywalny raz za razem.
źródło
SimpleImmutableEntry
Klasa par zgodna z HashMap:
źródło
super()
. Normalnie odciąłbym go, jeśli jest opcjonalny, tak jak jest tutaj.Najkrótsza para, jaką mogłam wymyślić, jest następująca, używając Lombok :
Posiada wszystkie zalety odpowiedzi z @arturh (z wyjątkiem porównywalności), ma
hashCode
,equals
,toString
a statyczne „konstruktor”.źródło
Apache Commons Lang 3.0+ ma kilka klas par: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
źródło
Kolejny sposób na wdrożenie Parowania z.
Prosta fabryka, więc nie musisz podawać typów. np. Pair.of („cześć”, 1);
źródło
of
. Przypomina niezmienne kolekcje Google Guava .o1
sięComparable
, choć nic nie wskazuje na to rzeczywiście wdrożyć ten interfejs. Jeśli jest to wymóg,FIRST
parametr typu powinien mieć wartośćFIRST extends Comparable<?>
.Co powiesz na http://www.javatuples.org/index.html Uważam, że jest to bardzo przydatne.
Javatuples oferuje tuple klas od jednego do dziesięciu elementów:
źródło
Pair
i mogłem sobie wyobrazić, że mogę używaćTriplet
raz na 50 lat. Teraz używam Lombok i tworzę małą 4-liniową klasę za każdym razem, gdy potrzebuję pary. Zatem „10 za dużo” jest dokładne.Bottom (0 element)
klasy? :)To zależy od tego, do czego chcesz go użyć. Typowym powodem jest iteracja po mapach, dla których po prostu to robisz (Java 5+):
źródło
Android zapewnia
Pair
klasę ( http://developer.android.com/reference/android/util/Pair.html ), tutaj implementacja:źródło
Objects.equal(..)
wymaga biblioteki Guava.Objects.equals(...)
język Java w 2011 r. (1.7).Największym problemem jest prawdopodobnie to, że nie można zapewnić niezmienności na A i B (zobacz Jak zapewnić, aby parametry typu były niezmienne ), więc
hashCode()
może dawać niespójne wyniki dla tej samej Pary po wstawieniu do kolekcji (na przykład dałoby to nieokreślone zachowanie , patrz Definiowanie równych pod względem zmiennych pól ). Dla konkretnej (nie ogólnej) klasy par programista może zapewnić niezmienność, ostrożnie wybierając A i B jako niezmienne.W każdym razie, usunięcie ostrzeżeń generycznych z odpowiedzi @ PeterLawrey (java 1.7):
Dodatki / poprawki bardzo mile widziane :) W szczególności nie jestem pewien co do mojego wykorzystania
Pair<?, ?>
.Aby uzyskać więcej informacji o tym, dlaczego ta składnia, zobacz Zapewnienie implementacji obiektów Porównywalne oraz szczegółowe wyjaśnienie Jak zaimplementować ogólną
max(Comparable a, Comparable b)
funkcję w Javie?źródło
Moim zdaniem nie ma pary w Javie, ponieważ jeśli chcesz dodać dodatkową funkcjonalność bezpośrednio na parze (np. Porównywalne), musisz powiązać typy. W C ++ po prostu nas to nie obchodzi, a jeśli typy tworzące parę nie mają
operator <
, topair::operator <
nie będą się również kompilować.Przykład porównywalnego bez ograniczenia:
Przykład Porównywalny z kontrolą czasu kompilacji, czy argumenty typu są porównywalne:
To dobrze, ale tym razem nie możesz używać nieporównywalnych typów jako argumentów typu w Pair. Można użyć wielu Komparatorów dla Pary w niektórych klasach użytkowych, ale ludzie w C ++ mogą tego nie dostać. Innym sposobem jest napisanie wielu klas w hierarchii typów z różnymi granicami argumentów typu, ale istnieje zbyt wiele możliwych granic i ich kombinacji ...
źródło
JavaFX (dostarczany w pakiecie z Javą 8) ma klasę Pair <A, B>
źródło
hashCode()
. Zauważ, że sama Java nie wywołuje tej metody. Dotyczy kodu użytkownika, w tym bibliotek.Jak wielu innych już powiedziało, tak naprawdę zależy od przypadku użycia, czy klasa Pair jest przydatna, czy nie.
Myślę, że dla funkcji prywatnego pomocnika jest całkowicie uzasadnione użycie klasy Pair, jeśli dzięki temu kod jest bardziej czytelny i nie jest warte wysiłku, aby stworzyć kolejną klasę wartości z całym kodem płyty kotłowej.
Z drugiej strony, jeśli Twój poziom abstrakcji wymaga wyraźnego udokumentowania semantyki klasy zawierającej dwa obiekty lub wartości, powinieneś napisać dla niej klasę. Zwykle dzieje się tak, jeśli dane są obiektem biznesowym.
Jak zawsze wymaga umiejętnego osądu.
Na drugie pytanie polecam klasę Pair z bibliotek Apache Commons. Można je uznać za rozszerzone standardowe biblioteki dla Java:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
Warto również zapoznać się z EqualsBuilder , HashCodeBuilder i ToStringBuilder Apache Commons , które upraszczają zapisywanie klas wartości dla obiektów biznesowych.
źródło
Możesz użyć klasy narzędzia javafx,
Pair
która służy temu samemu celowi, co para <> w c ++. https://docs.oracle.com/javafx/2/api/javafx/util/Pair.htmlźródło
Dobra Nowina
JavaFX
ma kluczową wartość Para.wystarczy dodać javafx jako zależność i zaimportować
javafx.util.Pair
;i użyj po prostu jak w
c++
.na przykład
źródło
Interfejs Map.Entry jest bardzo zbliżony do pary c ++. Spójrz na konkretne wdrożenie, takie jak AbstractMap.SimpleEntry i AbstractMap.SimpleImmutableEntry Pierwszy element to getKey (), a drugi to getValue ().
źródło
źródło
Zgodnie z naturą języka Java, przypuszczam, że ludzie tak naprawdę nie potrzebują
Pair
interfejsu, którego zwykle potrzebują. Oto przykład:Gdy więc ludzie chcą zwrócić dwie wartości, mogą wykonać następujące czynności:
Jest to dość lekkie rozwiązanie, które odpowiada na pytanie „Co to jest semantyczne
Pair<L,R>
?”. Odpowiedź brzmi: jest to kompilacja interfejsu z dwoma (może być różnymi) typami i ma metody zwracania każdego z nich. Od ciebie zależy, czy dodasz do niego kolejne semantyczne. Na przykład, jeśli używasz pozycji i NAPRAWDĘ chcesz wskazać to w swoim kodzie, możesz zdefiniowaćPositionX
iPositionY
toInteger
, aby utworzyćPair<PositionX,PositionY>
. Jeśli JSR 308 jest dostępny, możesz również użyć go wPair<@PositionX Integer, @PositionY Ingeger>
celu uproszczenia.EDYCJA: Jedną rzeczą, którą powinienem tutaj wskazać, jest to, że powyższa definicja wyraźnie odnosi się do nazwy parametru typu i nazwy metody. To odpowiedź na te argumenty, że
Pair
brak jest informacji semantycznej. W rzeczywistości metoda tagetL
oznacza „daj mi element odpowiadający typowi parametru typu L”, co coś znaczy.EDYCJA: Oto prosta klasa narzędzi, która może ułatwić życie:
stosowanie:
źródło
equals
,hashCode
itoString
?toString
, potrzebujesz więcej wiedzy na temat relacji między tymi dwoma polami.class
może być lepsze niż tylkointerface
dlatego, że może zaimplementować te rzeczy.Pomimo podobnej składni, Java i C ++ mają bardzo różne paradygmaty. Pisanie C ++ jak Java jest złym C ++, a pisanie Javy jak C ++ jest złe Java.
Dzięki IDE opartemu na odbiciu, takim jak Eclipse, pisanie niezbędnej funkcjonalności klasy „parowej” jest szybkie i proste. Utwórz klasę, zdefiniuj dwa pola, użyj różnych opcji menu „Generuj XX”, aby wypełnić klasę w ciągu kilku sekund. Być może będziesz musiał bardzo szybko wpisać „porównaj”, jeśli chcesz interfejs porównywalny.
Dzięki osobnym opcjom deklaracji / definicji w języku generatory kodu C ++ nie są tak dobre, więc ręczne pisanie małych klas narzędzi jest bardziej czasochłonne. Ponieważ para jest szablonem, nie musisz płacić za funkcje, których nie używasz, a funkcja typedef umożliwia przypisywanie znaczących nazw typów do kodu, więc zastrzeżenia dotyczące „braku semantyki” tak naprawdę nie wytrzymują.
źródło
Para byłaby dobrą rzeczą, aby być podstawową jednostką konstrukcyjną dla złożonych generycznych, na przykład, to jest z mojego kodu:
To jest tak samo jak Tuple Haskella
źródło
Pair
jest optymalny, ponieważ nie ma specjalnej semantyki. Posiadanie jasnej nazwy dla jasnej koncepcji jest dobre, ale szukanie nazwy, w której „pierwsze” i „drugie” działają dobrze, nie jest.Prosty sposób Object [] - może być użyty jako krotka wymiarowa
źródło
W przypadku języków programowania, takich jak Java, alternatywna struktura danych używana przez większość programistów do reprezentowania pary, podobnie jak struktury danych, to dwie tablice, a dane są dostępne za pośrednictwem tego samego indeksu
przykład: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
Nie jest to idealne, ponieważ dane powinny być ze sobą powiązane, ale okazują się również dość tanie. Ponadto, jeśli twój przypadek użycia wymaga przechowywania współrzędnych, lepiej zbudować własną strukturę danych.
Mam coś takiego w swojej bibliotece
źródło
Możesz użyć biblioteki AutoValue firmy Google - https://github.com/google/auto/tree/master/value .
Tworzysz bardzo małą klasę abstrakcyjną i adnotujesz ją za pomocą @AutoValue, a procesor adnotacji generuje dla ciebie konkretną klasę, która ma wartość semantyczną.
źródło
Oto niektóre biblioteki, które mają wiele stopni krotek dla Twojej wygody:
Wspomniano o innych bibliotekach zawierających przynajmniej
Pair
krotkę.W szczególności, w kontekście programowania funkcjonalnego, w którym wykorzystuje się dużo typowania strukturalnego, a nie typowego ( jak zaleca się w przyjętej odpowiedzi ), te biblioteki i ich krotki są bardzo przydatne.
źródło
Brian Goetz, Paul Sandoz i Stuart Marks wyjaśniają, dlaczego podczas sesji QA w Devoxx'14.
Posiadanie ogólnej klasy par w standardowej bibliotece zamieni się w dług techniczny po wprowadzeniu typów wartości .
Zobacz także: Czy Java SE 8 ma pary lub krotki?
źródło
kolejna implementacja Terse Lombok
źródło
Zauważyłem, że wszystkie implementacje Pary są tu rozrzucone, przypisując znaczenie kolejności dwóch wartości. Kiedy myślę o parze, myślę o kombinacji dwóch elementów, w których kolejność tych dwóch elementów nie ma znaczenia. Oto moja implementacja nieuporządkowanej pary, z
hashCode
iequals
zastępuje, aby zapewnić pożądane zachowanie w kolekcjach. Można także klonować.Ta implementacja została poprawnie przetestowana jednostkowo i wypróbowano użycie w zestawie i mapie.
Zauważ, że nie twierdzę, że opublikuję to w domenie publicznej. To jest kod, który właśnie napisałem do użytku w aplikacji, więc jeśli zamierzasz go użyć, powstrzymaj się od robienia bezpośredniej kopii i popsuć trochę komentarzami i nazwiskami. Złapać mój dryf?
źródło
Jeśli ktoś chce śmiertelnie prostą i łatwą w użyciu wersję, udostępniłem ją na https://github.com/lfac-pt/Java-Pair . Również ulepszenia są bardzo mile widziane!
źródło
com.sun.tools.javac.util.Pair to prosta implementacja pary. Można go znaleźć w pliku jdk1.7.0_51 \ lib \ tools.jar.
Poza org.apache.commons.lang3.tuple.Pair, nie jest to tylko interfejs.
źródło
stosowanie :
Niezmienne, tylko para!
źródło
Pair<Object, Object> pair = Pair.createPair("abc", "def")
ale myślę, że trzeba napisać zaPair.createPair((Object)"abc", (Object)"def")
pomocą twojego kodu?@SuppressWarnings("unchecked") public static <K, V, X, Y> Pair<X, Y> createPair(K key, V value) { return new Pair<X, Y>((X) key, (Y) value); }
ale nie wiem, czy to dobra praktykanew Pair<Object, Object>("abc", "def")
był najbardziej niezawodny w moich eksperymentach.