Warunki: nie modyfikuj oryginalnych list; Tylko JDK, brak bibliotek zewnętrznych. Punkty bonusowe za wersję jedno-liniową lub wersję JDK 1.3.
Czy istnieje prostszy sposób niż:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
Odpowiedzi:
W Javie 8:
źródło
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).distinct().collect(Collectors.toList());
Stream.of(listOne, listTwo).flatMap(Collection::stream).collect(Collectors.toList())
Z czubka głowy mogę skrócić go o jedną linię:
źródło
addAll()
obu. Próbowałem wszystkich tych, które sugerują, że nie będę kopiować list, a one skutkują dużym obciążeniem, którego nie potrzebowaliśmy tym razem.addAll(Collection)
zwraca aboolean
.Możesz użyć biblioteki wspólnych kolekcji Apache :
źródło
Jednym z twoich wymagań jest zachowanie oryginalnych list. Jeśli utworzysz nową listę i użyjesz
addAll()
, skutecznie podwajasz liczbę odwołań do obiektów na twoich listach. Może to prowadzić do problemów z pamięcią, jeśli twoje listy są bardzo duże.Jeśli nie musisz modyfikować połączonego wyniku, możesz tego uniknąć za pomocą niestandardowej implementacji listy. Niestandardowa klasa implementacji to oczywiście więcej niż jedna linia ... ale korzystanie z niej jest krótkie i słodkie.
CompositeUnmodifiableList.java:
Stosowanie:
źródło
Collections.unmodifiableList()
metody, która owija listę, aby uczynić ją niemodyfikowalną.CompositeUnmodifiableList
robi to samo, tyle że zawija dwie listy i zapewnia skonkatenowany widok. Wszystkie punkty, oCompositeUnmodifiableList
których mówisz, są również prawdziweCollections.unmodifiableList()
.List<? extends E>
Prawdopodobnie nie prostsze, ale intrygujące i brzydkie:
Nie używaj go w kodzie produkcyjnym ...;)
źródło
Kolejny jednowierszowy program Java 8:
Jako bonus, ponieważ
Stream.of()
jest on variadic, możesz połączyć dowolną liczbę list.źródło
x -> x.stream()
można zastąpićCollection::stream
.List::stream
.Nie prościej, ale bez zmiany narzutu:
źródło
Znalazłem to pytanie, próbując połączyć dowolną liczbę list, nie wspominając o bibliotekach zewnętrznych. Być może pomoże to komuś innemu:
Przydatne, jeśli chcesz zastosować tę samą logikę do wielu różnych kolekcji w jednym for ().
źródło
com.google.common.collect.Iterators#concat(java.util.Iterator<? extends java.util.Iterator<? extends T>>)
zamiastIterables#concat()
; ponieważ później nadal kopiuje elementy do temp link!Proponowane rozwiązanie dotyczy trzech list, choć można je również zastosować do dwóch list. W Javie 8 możemy skorzystać z Stream.of lub Stream.concat jako:
Stream.concat
pobiera dwa strumienie jako dane wejściowe i tworzy leniwie połączony strumień, którego elementami są wszystkie elementy pierwszego strumienia, a następnie wszystkie elementy drugiego strumienia. Ponieważ mamy trzy listy, zastosowaliśmy tę metodę (Stream.concat
) dwa razy.Możemy również napisać klasę narzędzia za pomocą metody, która pobiera dowolną liczbę list (używając varargs ) i zwraca skonkatenowaną listę jako:
Następnie możemy skorzystać z tej metody jako:
źródło
Oto rozwiązanie Java 8 wykorzystujące dwie linie:
Należy pamiętać, że tej metody nie należy stosować, jeśli
newList
nie jest znane i może być już udostępnione innym wątkomnewList
jest strumieniem równoległym, a dostęp do niegonewList
nie jest synchronizowany ani bezpieczny dla wątkówze względu na skutki uboczne.
Oba powyższe warunki nie dotyczą powyższego przypadku połączenia dwóch list, więc jest to bezpieczne.
Na podstawie tej odpowiedzi na inne pytanie.
źródło
newList
nie jest zauważalny przez żaden inny wątek. Ale masz rację, że prawdopodobnie nie należy tego robić, jeśli nie wiadomo, skąd pochodzi wartośćnewList
(na przykład, jeślinewList
został przekazany jako parametr..forEach(newList::addAll);
zamiast.collect(Collectors.toList());
?List<List<Object>>
. To, co możesz mieć na myśli, to coś takiego: stackoverflow.com/questions/189559/…flatMap
.Jest to prosta i tylko jedna linia, ale doda zawartość listTwo do listOne. Czy naprawdę musisz umieścić zawartość na trzeciej liście?
źródło
Nieco prostsze:
źródło
List
Struktura nie nakłada żadnych ograniczeń wyjątkowość. Możesz usunąć duplikaty, robiąc to samo z zestawami.Set<String> newSet = new HashSet<>(setOne); newSet.addAll(setTwo);
Nieco krótszy byłby:
źródło
Możesz utworzyć ogólną metodę narzędzia Java 8 , aby połączyć dowolną liczbę list .
źródło
Możesz zrobić oneliner, jeśli lista celów jest zadeklarowana.
źródło
W Javie 8 (w drugą stronę):
źródło
inne rozwiązanie liniowe wykorzystujące
Java8
strumień, ponieważflatMap
rozwiązanie jest już opublikowane, oto rozwiązanie bezflatMap
lub
kod
wynik
źródło
flatMap
, ponieważ listy są iterowane tylko raz, gdy są gromadzoneNajmądrzejszy moim zdaniem:
źródło
@SafeVarargs
!Możesz to zrobić za pomocą importu statycznego i klasy pomocniczej
nb generacja tej klasy mogłaby prawdopodobnie ulec poprawie
Następnie możesz robić takie rzeczy jak
źródło
Wersja Java 8 z obsługą łączenia według klucza obiektu:
źródło
źródło
Użyj klasy pomocnika.
Sugeruję:
źródło
źródło
Możemy dołączyć do 2 list za pomocą java8 z 2 podejściami.
1) Za pomocą concat:
2) Korzystanie z flatMap:
źródło
Prawie odpowiedzi sugerują użycie ArrayList.
Wolę używać LinkedList do wydajnych operacji dodawania.
ArrayList add jest amortyzowane przez O (1), ale w najgorszym przypadku O (n), ponieważ należy zmienić rozmiar tablicy i skopiować. Podczas gdy LinkedList add jest zawsze stałą O (1).
więcej informacji https://stackoverflow.com/a/322742/311420
źródło
Nie twierdzę, że to proste, ale wspomniałeś o premii za linijki ;-)
źródło
Nie ma mowy w pobliżu jednej linijki, ale myślę, że jest to najprostsze:
źródło
Oto podejście wykorzystujące strumienie i Javę 8, jeśli listy mają różne typy i chcesz je połączyć z listą innego typu.
źródło
Jeśli chcesz to zrobić statycznie, możesz:
W przykładach użyto 2 zestawów EnumSet w porządku naturalnym (== porządek Enum)
A, B
i łączy się następnie naALL
liście.źródło
źródło