sourcecode

스트림을 사용하여 맵을 생성할 때 중복 무시

copyscript 2022. 8. 9. 22:55
반응형

스트림을 사용하여 맵을 생성할 때 중복 무시

Map<String, String> phoneBook = people.stream()
                                      .collect(toMap(Person::getName,
                                                     Person::getAddress));

java.lang.IllegalStateException: Duplicate key중복된 요소가 발견되었을 때.

지도에 값을 추가할 때 이러한 예외를 무시할 수 있습니까?

중복된 키가 있는 경우 해당 중복된 키를 무시하기만 하면 계속됩니다.

하면 '아,어,어,어,어,어,어,어'를 사용해서 할 수 '를 사용해서 할 수 있어요.mergeFunction파라미터:

Map<String, String> phoneBook = 
    people.stream()
          .collect(Collectors.toMap(
             Person::getName,
             Person::getAddress,
             (address1, address2) -> {
                 System.out.println("duplicate key found!");
                 return address1;
             }
          ));

mergeFunction는 같은 키에 관련된2개의 값으로 동작하는 함수입니다. adress1 및 을 할 때 처음 에 대응합니다.adress2아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.이 람다는 첫 번째 주소를 유지하도록 지시합니다.

JavaDocs에서 설명한 바와 같이:

중복이 되어 있는 (「」에 )Object.equals(Object) 「 」IllegalStateException이치노에 중복이 있는 " " 를 사용합니다.toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)★★★★★★ 。

그러니까 대신 쓰세요.맵에 넣을 중복 항목을 결정하는 병합 기능을 제공하기만 하면 됩니다.

예를 들어, 어떤 것이든 상관 없으면 그냥 전화하세요.

Map<String, String> phoneBook = 
        people.stream()
              .collect(Collectors.toMap(Person::getName, 
                                        Person::getAddress, 
                                        (a1, a2) -> a1));

alaster의 답변이 큰 도움이 되었습니다만, 만약 누군가가 데이터를 그룹화하려고 한다면, 의미 있는 정보를 추가하고 싶습니다.

2개의 「」가 있는 는, 「」입니다.Orderscode 다르다quantity수량을 합산하고 싶은 경우, 다음과 같이 할 수 있습니다.

List<Order> listQuantidade = new ArrayList<>();
listOrders.add(new Order("COD_1", 1L));
listOrders.add(new Order("COD_1", 5L));
listOrders.add(new Order("COD_1", 3L));
listOrders.add(new Order("COD_2", 3L));
listOrders.add(new Order("COD_3", 4L));

listOrders.collect(Collectors.toMap(Order::getCode, 
                                    o -> o.getQuantity(), 
                                    (o1, o2) -> o1 + o2));

결과:

{COD_3=4, COD_2=3, COD_1=9}

또는 자바독에서 주소를 조합할 수 있습니다.

 Map<String, String> phoneBook
     people.stream().collect(toMap(Person::getName,
                                   Person::getAddress,
                                   (s, a) -> s + ", " + a));

오브젝트별 그룹화

Map<Integer, Data> dataMap = dataList.stream().collect(Collectors.toMap(Data::getId, data-> data, (data1, data2)-> {LOG.info("Duplicate Group For :" + data2.getId());return data1;}));

이 문제가 발생하지만 스트림 중인 맵에 중복 키가 없는 경우 key Mapper 함수가 null 값을 반환하지 않는지 확인하십시오.

두 번째 요소를 처리할 때 1이 실제로 키가 아닌 엔트리의 인 경우 예외는 "Duplicate key 1"로 표시되므로 이를 추적하기가 매우 어렵습니다.

제 경우 key Mapper 함수가 다른 맵에서 값을 검색하려고 했지만 문자열의 오타로 인해 null 값이 반환되었습니다.

final Map<String, String> doop = new HashMap<>();
doop.put("a", "1");
doop.put("b", "2");

final Map<String, String> lookup = new HashMap<>();
doop.put("c", "e");
doop.put("d", "f");

doop.entrySet().stream().collect(Collectors.toMap(e -> lookup.get(e.getKey()), e -> e.getValue()));

toMap자주 작동하지만 항상 그렇지는 않습니다. 자바 스트림 toUniqueMap뭐랄까...

가장 쉬운 방법은Collectors.groupingBy 대신 Collectors.toMap.

A가 반환됩니다.List기본적으로는 output을 입력하지만 충돌 문제는 해결되었습니다. 또한 다중이 존재하는 경우 원하는 결과를 얻을 수도 있습니다.

  Map<String, List<Person>> phoneBook = people.stream()
          .collect(groupingBy((x) -> x.name));

만약 a가Set특정 이름과 연결된 주소의 유형 모음,groupingBy그것도 가능합니다.

Map<String, Set<String>> phoneBook = people.stream()
          .collect(groupingBy((x) -> x.name, mapping((x) -> x.address, toSet())));

다른 방법은 해시 또는 집합으로 시작하는 것입니다.출력 스트림에서 키가 중복되지 않도록 주의 깊게 추적합니다.여기 살아남은 예가 있어요가끔...

오브젝트를 그룹화할 때 이러한 문제가 발생했기 때문에 항상 간단한 방법으로 해결했습니다.java.util을 사용하여 커스텀필터를 실행합니다.선택한 속성을 가진 중복 개체를 제거합니다.

Set<String> uniqueNames = new HashSet<>();
Map<String, String> phoneBook = people
                  .stream()
                  .filter(person -> person != null && !uniqueNames.add(person.getName()))
                  .collect(toMap(Person::getName, Person::getAddress));

이것이 같은 문제를 가지고 있는 사람에게 도움이 되기를 바랍니다!

완전성을 위해 중복되는 것을 1개로 줄이는 방법을 다음에 나타냅니다.

마지막 순서로 문제가 없는 경우:

  Map<String, Person> phoneBook = people.stream()
          .collect(groupingBy(x -> x.name, reducing(null, identity(), (first, last) -> last)));

첫 번째만 원하는 경우:

  Map<String, Person> phoneBook = people.stream()
          .collect(groupingBy(x -> x.name, reducing(null, identity(), (first, last) -> first != null ? first : last)));

마지막이지만 "문자열로서의 주소"를 원하는 경우(사용하지 않음)identity()(파라미터로 설정합니다.

  Map<String, String> phoneBook = people.stream()
          .collect(groupingBy(x -> x.name, reducing(null, x -> x.address, (first, last) -> last)));

원천

그래서 본질적으로는groupingBy와 짝을 이루다reducingCollector는 다음과 같이 동작하기 시작합니다.toMap수집기가 mergeFunction과 유사한 기능을 가지고 있습니다.그리고 같은 최종 결과...

람다 기능을 사용할 수 있습니다.키(...)에서 키 문자열로 비교합니다.

List<Blog> blogsNoDuplicates = blogs.stream()
            .collect(toMap(b->key(b), b->b, (b1, b2) -> b1))  // b.getAuthor() <~>key(b) as Key criteria for Duplicate elimination
            .values().stream().collect(Collectors.toList());

static String key(Blog b){
    return b.getTitle()+b.getAuthor(); // make key as criteria of distinction
}

사용자가 있다고 가정하면 오브젝트 리스트

  Map<String, String> phoneBook=people.stream()
                                        .collect(toMap(Person::getName, Person::getAddress));

이제 두 가지 단계가 필요합니다.

1)

people =removeDuplicate(people);

2)

Map<String, String> phoneBook=people.stream()
                                        .collect(toMap(Person::getName, Person::getAddress));

중복을 제거하는 방법은 다음과 같습니다.

public static List removeDuplicate(Collection<Person>  list) {
        if(list ==null || list.isEmpty()){
            return null;
        }

        Object removedDuplicateList =
                list.stream()
                     .distinct()
                     .collect(Collectors.toList());
     return (List) removedDuplicateList;

      }

여기에 전체 예제를 추가하는 중

 package com.example.khan.vaquar;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class RemovedDuplicate {

    public static void main(String[] args) {
        Person vaquar = new Person(1, "Vaquar", "Khan");
        Person zidan = new Person(2, "Zidan", "Khan");
        Person zerina = new Person(3, "Zerina", "Khan");

        // Add some random persons
        Collection<Person> duplicateList = Arrays.asList(vaquar, zidan, zerina, vaquar, zidan, vaquar);

        //
        System.out.println("Before removed duplicate list" + duplicateList);
        //
        Collection<Person> nonDuplicateList = removeDuplicate(duplicateList);
        //
        System.out.println("");
        System.out.println("After removed duplicate list" + nonDuplicateList);
        ;

        // 1) solution Working code
        Map<Object, Object> k = nonDuplicateList.stream().distinct()
                .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
        System.out.println("");
        System.out.println("Result 1 using method_______________________________________________");
        System.out.println("k" + k);
        System.out.println("_____________________________________________________________________");

        // 2) solution using inline distinct()
        Map<Object, Object> k1 = duplicateList.stream().distinct()
                .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
        System.out.println("");
        System.out.println("Result 2 using inline_______________________________________________");
        System.out.println("k1" + k1);
        System.out.println("_____________________________________________________________________");

        //breacking code
        System.out.println("");
        System.out.println("Throwing exception _______________________________________________");
        Map<Object, Object> k2 = duplicateList.stream()
                .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1));
        System.out.println("");
        System.out.println("k2" + k2);
        System.out.println("_____________________________________________________________________");
    }

    public static List removeDuplicate(Collection<Person> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }

        Object removedDuplicateList = list.stream().distinct().collect(Collectors.toList());
        return (List) removedDuplicateList;

    }

}

// Model class
class Person {
    public Person(Integer id, String fname, String lname) {
        super();
        this.id = id;
        this.fname = fname;
        this.lname = lname;
    }

    private Integer id;
    private String fname;
    private String lname;

    // Getters and Setters

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFname() {
        return fname;
    }

    public void setFname(String fname) {
        this.fname = fname;
    }

    public String getLname() {
        return lname;
    }

    public void setLname(String lname) {
        this.lname = lname;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", fname=" + fname + ", lname=" + lname + "]";
    }

}

결과:

Before removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan]]

After removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan]]

Result 1 using method_______________________________________________
k{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]}
_____________________________________________________________________

Result 2 using inline_______________________________________________
k1{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]}
_____________________________________________________________________

Throwing exception _______________________________________________
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Person [id=1, fname=Vaquar, lname=Khan]
    at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
    at java.util.HashMap.merge(HashMap.java:1253)
    at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at com.example.khan.vaquar.RemovedDuplicate.main(RemovedDuplicate.java:48)

같은 케이스에서 가장 간단한 솔루션(복제 키의 맵 값을 덮어쓰는 것을 전제로 합니다)은 다음과 같습니다.

Map<String, String> phoneBook = 
       people.stream()
           .collect(Collectors.toMap(Person::getName, 
                                  Person::getAddress, 
                                        (key1, key2)-> key2));

언급URL : https://stackoverflow.com/questions/32312876/ignore-duplicates-when-producing-map-using-streams

반응형