Mergowanie obiektów za pomocą pola

0

Otrzymuje takie dane:

{
  "name": "test 1234",
  "desc": "test 568",
  "number": 1
},
{
  "name": "test 1234",
  "desc": "test 568",
  "number": 2
},
{
  "name": "cos innego 1234",
  "desc": "cos inego 568",
  "number": 3
},
{
  "name": "jeszcze cos innego 1234",
  "desc": "jeszcze cos inego 568",
  "number": 4
}

gdy wykonuje to:

....
List<MainObj> result = new ArrayList<>();
for (Adr adr : items) {
	MainObj mainObj = new MainObj();

	mainObj.setName(adr.getName());
	mainObj.setDesc(adr.getDesc());
	mainObj.setNumber(adr.getNumber());

	result.add(mainObj);
}

return result;

a teraz jak to przerobić abym otrzymał cos w stylu:

{
  "name": "test 1234",
  "desc": "test 568",
  "numbers": [1,2]
},
{
  "name": "cos innego 1234",
  "desc": "cos inego 568",
  "numbers": [3]
},
{
  "name": "jeszcze cos innego 1234",
  "desc": "jeszcze cos inego 568",
  "numbers": [4]
}

czyli scala się jeśli pole name i desc są takie same a number robi robi się listą

1

Pierwszego jsona przeparsować gsonem na jakąś listę zawierającą elementy takiej klasy:

class MyFirstClass {
  String name;
  String desc; 
  Integer number;
}

A później listę takich obiektów jakąś funkcją i streamem potraktować na kolekcję takiej klasy:

class MyTargetClass {
  String name;
  String desc; 
  List<Integer> number;
}

A funkcja może implementować interfejs Function<MyFirstClass, MyTargetClass>

0

.stream().groupingBy(x->key(x), Collectors.toList()) ?

0

@Shalom: z tym groupingBy może i by było fajnie ale musze to zgrupować po co najmniej dwóch polach (name, desc) i jeszcze number zmienic na numbers jako listę

0

I co dokładnie jest tu problemem? Bo chyba nie bardzo widzę. Grupuj po jakimś Tuple2<String,String> a grouping by samo załatwi żeby zgrupowane rekordy zebrały się w listę.

0

Nie mozesz zrobic tego na piechote? Beda za 3 linijki + wlasna klasa na klucz w mapie, wtedy robisz cos takiego (pisze z pamieci):

Map<Key, List<Integer>> mapa = new HashMap<>();
for (MainObj o : lista) {
  mapa.merge(new Key(o.name, o.desc), new ArrayList<>(o.number), (oldVal, x) -> { oldVal.add(o.number); return oldVal; });
}
return mapa;

Map#merge: https://nurkiewicz.com/2019/03/mapmerge-one-method-to-rule-them-all.html

0

@Charles_Ray: mimo wszystko gdy robie sobie prostego fora po mapa

    mapa.forEach((key, integers) -> {
			System.out.println(key.name + "-" + key.desc + "-" + integers.stream().collect(Collectors.toList()));

		});

to dostaje wartości niby z tym samym kluczem ale nie zmergowane, problemem jest chyba to że za każdym razem jest tworzony nowy obiekt new Key() ?

1

Problem jest w tym, że pewnie nie napisales equals i hashCode :)

0

@Charles_Ray: racja, zaczyna działać, oprócz tego że jeszcze dostaje tutaj na końcówce { oldVal.add(o.number); return oldVal; } w o nulla przez pewnie {} ? Jak temu zaradzić?

0

Ale co jest dokladnie nullem?

0

@Charles_Ray: o :)

1

Hmm, to odfiltruj? Te obiekty generalnie Ty dostarczasz. Jak to mozliwe, że tam jest null - tak przychodzi w jsonie?

0

@Charles_Ray: to nie o odfiltrowanie chodzi... to przez {} lambda ?

0

Nie wiem, pokaz kod

0

zastosowałem jednak groupingBy. Stworzyłem coś takiego - zwraca mi już pożądaną listę List<Adr>

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

		items.stream()
			.collect(Collectors.groupingBy(x -> new Key(x.getName(), x.getDesc()),
					Collectors.mapping(p -> p.getNumber(), Collectors.toList())))
			.forEach((key, integers) -> {
				results.add(new Adr(key.getName(), key.getDesc(), integers.stream().collect(Collectors.toSet())));
			});
  

jak można to skrócić to będzie całkiem fajnie :) ale juz i tak jestem zadowolony :)

0

Zamiast forEach mozesz zrobic .entrySet().stream() i po prostu zmapowac do listy.

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