List<MyDTO> łaczenie kolekcji

0

Siemanko
mam takiego jsona (moja List<MyDTO>)

[
	{
		id: 2134
		active: false
		ter: [test1]
	},
	{
		id: 2134
		active: false
		ter: [test2]
	},
	{
		id: 1111
		active: false
		ter: [test34]
	},
]

i chce to zmergowac w taki sposób aby powstało:

[
	{
		id: 2134
		active: false
		ter: [test1, test2]
	},
	{
		id: 1111
		active: false
		ter: [test34]
	},
]

bazuje na MyDTO a nie na mapach etc.

1

Chcesz to w javie połączyć za pomocą kodu?

import java.util.*;
import java.util.stream.*;

public class HelloWorld {

     public static void main(String []args) {
        List<MyDTO> list = Arrays.asList(
            new MyDTO(2134, false, "test1"),
            new MyDTO(2134, false, "test2"),
            new MyDTO(1111, false, "test34")
        );
        
        Map<KeyMyDTO, List<MyDTO>> map = list.stream()
        .collect(Collectors.groupingBy(i -> i.toKey()));
        
        List<MyDTO> merged =  map.entrySet().stream()
        .map(e -> new MyDTO(e.getKey(), MyDTO.extractTers(e.getValue())))
        .collect(Collectors.toList());
         
        System.out.println(merged);
     }
}

class MyDTO {
    
    int id;
    boolean active;
    String[] ter;

    MyDTO(int id, boolean active, String ... ter) {
        this.id = id;
        this.active = active;
        this.ter = ter;
    }
    
    MyDTO(KeyMyDTO key, String[] ter) {
        this.id = key.id;
        this.active = key.active;
        this.ter = ter;
    }
    
    KeyMyDTO toKey() {
        return new KeyMyDTO(id, active);
    }

    static String[] extractTers(List<MyDTO> list) {
        return list.stream()
        .flatMap(a -> Arrays.asList(a.ter).stream()).toArray(String[]::new);
    }
     
    public String toString() {
        return "{id: " + id + ", active: " + active  + ", ter: ["    + String.join(", ", ter) + "]}" ;
    }
}

class KeyMyDTO {
    int id;
    boolean active;

    KeyMyDTO(int id, boolean active) {
        this.id = id;
        this.active = active;
    }
    
    public boolean equals(Object that) {
        return that != null && that.getClass() == getClass() && eq((KeyMyDTO)that);
    }

    boolean eq(KeyMyDTO that) {
        return that.id == id && that.active == active;
    }
    
    public int hashCode() {
        return id * 2 + (active ? 1 : 0);
    }
}

Już zapomniałem jaka Java jest rozwlekła :D

0

a pomożecie mi jeszcze połączyć po kluczu taką mapę

 Map<String, String> result2 = new HashMap<>();
       result2.put("1234", "test1");
       result2.put("1234", "test1234");
       result2.put("444", "test1");
     

aby otrzymać:

1234, [test1, test1234]
444, [test1]

kombinuje z merge, flatMap ale nic mi nie wychodzi :/

1

To co potrzebujesz to MultiMap. Przykładowo z Vavr https://static.javadoc.io/io.vavr/vavr/0.10 .2/io/vavr/collection/HashMultimap.html albo z guavy https://guava.dev/releases/23.0/api/docs/com/google/common/collect/Multimap.html

Zwykła hashmapa javowa trzyma max 1 wartość pod kluczem i jeśli napiszesz jak niżej:

result2.put("1234", "test1");
result2.put("1234", "test1234");

to wartość "test1" zostanie utracona (nadpisana).
To co potrzbujesz to Map<String, List<String>> - ale to jest własnie multimapa i podałem jej dwie gotowe implementacje.

Używanie HashMap<String, List<String>> jest też możliwe, ale jest mniej wygodne.(Choć jeśli zamiast put będziesz używał odpowiedniego merge to się da).

0

Możesz jeszcze użyć Apache Commons MultiValueMap - tak przynajmniej twierdzi wujek G.

0

No własnie musze otrzymać ```
Map<String, List<String>>


robię to teraz tak: 

result2.merge("1234", "test1", (s, s2) -> s + s2);

itd. każdego merge
tylko, że wychodzi mi wtedy Map<String, String>
0

Jak miałoby to działać, skoro „+” nie działa w Javie dla list?

0

Wiem, że nie ale jak to teraz przerobić?

1

Napisałem Ci.
Użyj gotowej kolekcji. Jest i działa.
Jak chcesz rzeźbić sam - to:

  1. Mape musisz od razu deklarować jako Map<String, List<String>> - mapa nie zmieni się magicznie ze Map<String,String> w mapę list, jesli dodasz element.
  2. Wtedy wywołanie merge musisz przerobić:
    drugi argument (value) to teraz lista jednoelementowa (jak nic nie było jeszcze pod danym kluczem to wstawiasz Collections.sigletonList("test1")
    a trzeci argument - funkcja mapująca - ma teraz postać:
    (s, s2) -> { var list = new LinkedList(s); list.addAll(s2); return list;} (offtopic - ładny rak to java.util. - może ktoś wie jak to lepij zapisać, może jest coś w nowszych wersjach javy? ).
1

Chyba miao by list.addAll(s2); zamiast list.add(s2); ?

jarekr000000 napisał(a):

offtopic - ładny rak to java.util. - może ktoś wie jak to lepij zapisać, może jest coś w nowszych wersjach javy?

Dziwnych pomysłów w internecie ludzie mają dużo. Z jednolinijkowców najbardziej podoba mi się Stream.concat(listOne.stream(), listTwo.stream()).collect(Collectors.toList())

0

Pytanie czy akurat w tym przypadku potrzebujesz laczyc kolekcje, bo masz dwa pola po jednym stanie i liste stringow ... wiec.. keep it simple

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