Optymalizacja scalenia dwóch List i unique

0

Czy ktoś ma lepszy pomysł na scalenie dwóch List (różnych obiektów!) i odrzucenie powtórzeń po jednej z wartości obiektu.
Chodzi o to czy da sie zrobić ładniej/lepiej/krócej/optymalniej niż to co wypociłem poniżej?

		List<T> results = new ArrayList<>();

		List<T> tList = getAll();
		List<E> eList = getFew();

		for(T t : tList) {
			E e = eList.stream()
				.filter(a -> a.getEid().equals(t.getTid()))
				.findFirst()
				.orElse(null);

			if(e == null) {
				results.add(t);
			}
		}

3

Wersja 2.0 doczytana :p
Zamień eList na Set, ale elementów Id i użyj metody contains. Zmniejszysz złożoność operacji z kwadratowej do liniowej
BTW twój smosob użycia optionali to anty przykład. Nie wypakowuj Optionala tylko użyj metody ifPresentifPresentOrElse​ lub isEmpty

UPDATE Optionaa używa się się tak

eList.stream()
  .filter(e -> e.getEid().equals(t.getTid()))
  .findFirst()
  .ifPresentOrElse​(e -> (), () ->results.add(t)); //co tu napisać jak nie jest pusty?

Albo w zasadzie tak :P

final boolean isEmpty = eList.stream()
  .filter(e -> e.getEid().equals(t.getTid()))
  .findFirst()
  .isEmpty();
if (isEmpty) {
  results.add(t);
}

A cały kod napisałbym tak:

final List<T> tList = getAll();
final List<E> eList = getFew();
final Set<Id> eIdSet = eList.stream().map(e -> e.getEid).collect(toSet())
final List<T> results = tList.stream().filter(t -> !eIdSet.contains(t.getTid()).collect(toList())
1

Ja bym się nie pchał na siłę w stream API. Jak masz poprawnie zaimplementowane hashCode() i equals(), to pakujesz zawartość obu list do HashSet i masz unikalny zbiór wartości.
Jak nie masz, to robisz sobie po wrapper żeby te metody zaimplementować poprawnie (albo tak jak potrzebujesz), opakowujesz wszystkie elementy w to i znowu ładujesz w hashset, na koniec odwijasz.

0

@biurostron:

Czy ktoś ma lepszy pomysł na scalenie dwóch List (różnych obiektów!) i odrzucenie powtórzeń po jednej z wartości obiektu.

Albo źle to rozumiem, albo to zdanie przeczy sobie. Jak chcesz odrzucić zduplikowane obiekty, które są innych typów? W kodzie widzę sprawdzenie po ID, więc nie chcesz odrzucić tych samych obiektów a tylko te które mają ten sam id tak?

Gdyby te obiekty miały wspólny interfejs albo klasę bazową, to można by było je trzymać w jednej liście i problem się wtedy dosyć łatwo rozwiązuje nie?

Brakuje mi tutaj tzw. kontekstu: po co to robisz i co dalej z tymi danymi robić będziesz.

1

Jeśli dobrze rozumiem:

  1. Masz listę obiektów T i listę obiektów E
  2. Chcesz uzyskać listę obiektów T ale tylko jeśli id takiego obiektu nie jest jednym z id w liście obiektów E?
Set<ID> blackList = eList.stream().map(E::getEid).collect(Collectors.toSet());
List<T> filtered = tList.stream().filter(x->!blackList.contains(x.getTid())).toList();

edit: w sumie to samo co sugerował @KamilAdam

3

Według mnie jeżeli w ogóle jesteś zmuszony łączyć dwie listy różnych obiektów to masz gdzieś indziej dużo większy problem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1