자바 8 에 서 는 Stream 을 사용 하여 List 를 맵 으로 돌려 사용 하 게 합 니 다.

7121 단어 Java8ListMap
자바 의 새로운 특성 인 Collectors.toMap()을 사용 하여 List 를 Map 으로 변환 할 때 발견 하기 어 려 운 문제 가 있 으 므 로 예비 조 사 를 정리 합 니 다.
공침 위험
java.lang.NullPointerException
List 에 null 값 이 있 을 때 Collectors.toMap()을 사용 하여 Map 으로 전환 할 때 자바.lang.NullPointer Exception 을 다음 과 같이 보고 합 니 다.

List<SdsTest> sdsTests = new ArrayList<>();
    SdsTest sds1 = new SdsTest("aaa","aaa");
    SdsTest sds2 = new SdsTest("bbb",null);

    sdsTests.add(sds1);
    sdsTests.add(sds2);

    Map<String, String> map = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, SdsTest::getAge));    
    System.out.println(map.toString());

---------
    :
Exception in thread "main" java.lang.NullPointerException
    at java.util.HashMap.merge(HashMap.java:1216)
    at java.util.stream.Collectors.lambda$toMap$150(Collectors.java:1320)
    .....
원인 은toMap()방법 에서Map.merge()방법 을 사용 하여 합병 할 때 merge 는 value 가 null 로 인해 발생 하 는 것 을 허용 하지 않 습 니 다.소스 코드 는 다음 과 같 습 니 다.

default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    //       value   null
    Objects.requireNonNull(value);
    V oldValue = get(key);
    V newValue = (oldValue == null) ? value : remappingFunction.apply(oldValue, value);
    ...
해결 방법
업무 제 어 는 Null 값 이 나타 나 지 않도록 합 니 다.[Null 이 있 는 곳 에 기본 값 을 부여 할 수 있 습 니 다.]변환 할 때 판단 을 추가 하고 null 이면 기본 값 을 줍 니 다.

Map<String, String> map = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, sdsTest -> sdsTest.getAge() == null ? "0" : sdsTest.getAge()));
collect(..)로 구축,빈 값 허용

Map<String, String> nmap = sdsTests.stream().collect(HashMap::new,(k, v) -> k.put(v.getName(), v.getAge()), HashMap::putAll);
// TODO      Map    NPE  
Optional 을 사용 하여 값 을 포장 합 니 다.

Map<String, Optional<String>> opmap = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, sdsTest -> Optional.ofNullable(sdsTest.getAge())));
System.out.println("bbb.age=" + opmap.get("bbb").orElse("0"));
------------
  :
bbb.age=0
건의
  • 우선 업무 통제,리스트 에 Null 이 존재 하지 않도록 한다
  • 그 다음 에 네 번 째 방법 을 추천 합 니 다.[Optional 을 사용 하여 값 을 포장 합 니 다]NPE 문 제 를 잘 피 할 수 있 습 니 다
  • key 중복 위험
    java.lang.IllegalStateException: Duplicate key xx
    List 에 중복 값 이 있 을 때 Collectors.toMap()을 사용 하여 Map 으로 전환 하면 java.lang.IllegalState 예외:Duplicate key xx,예 를 들 어
    
    List<SdsTest> sdsTests = new ArrayList<>();
        SdsTest sds1 = new SdsTest("aaa","aaa");
        SdsTest sds2 = new SdsTest("aaa","ccc");
    
        sdsTests.add(sds1);
        sdsTests.add(sds2);
    
        Map<String, String> map = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, SdsTest::getAge));    
        System.out.println(map.toString());
    
    ---------
        :
    Exception in thread "main" java.lang.IllegalStateException: Duplicate key aaa
            at java.util.stream.Collectors.lambda$throwingMerger$92(Collectors.java:133)
            at java.util.stream.Collectors$$Lambda$6/1177096266.apply(Unknown Source)
            at java.util.HashMap.merge(HashMap.java:1245)
                .....
    이 유 는 두 매개 변수의 toMap(xx,xx)방법 으로 중복 key 가 merge 를 촉발 할 때 직접 이상 을 던 지기 때 문 입 니 다.원본 코드 는 다음 과 같 습 니 다.
    
    public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper) {
         //      throwingMerger()
         return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
    }
    다음은 throwingMerger()방법 을 살 펴 보 겠 습 니 다.[주의 방법 설명]
    
    /**
     * Returns a merge function, suitable for use in
     * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
     * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
     * throws {@code IllegalStateException}.  This can be used to enforce the
     * assumption that the elements being collected are distinct.
     *
     * @param <T> the type of input arguments to the merge function
     * @return a merge function which always throw {@code IllegalStateException}
     */
     private static <T> BinaryOperator<T> throwingMerger() {
          return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
     }
    ...
    해결 방법
    4.567917.업무 통 제 는 가능 한 한 중복 치가 나타 나 지 않도록 한다.4.567918.
  • 중복 key 가 나타 날 때 뒤의 value 를 사용 하여 앞의 value 를 덮어 씁 니 다
  • 
    SdsTest sds1 = new SdsTest("aaa","aaa");
    SdsTest sds2 = new SdsTest("bbb","bbb");
    SdsTest sds3 = new SdsTest("aaa","ccc");
    
    sdsTests.add(sds1);
    sdsTests.add(sds2);
    sdsTests.add(sds3);
    
    //    
    Map<String, String> nmap = sdsTests.stream().collect(HashMap::new,(k, v) -> k.put(v.getName(), v.getAge()), HashMap::putAll);
    System.out.println("nmap->:" + nmap.toString());
    
    //    
    Map<String, String> nmap1 = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, SdsTest::getAge, (k1, k2) -> k2));
    System.out.println("nmap1->:" + nmap1.toString());
    ...
    ----------------------
      :
    nmap->:{aaa=ccc, bbb=bbb}
    nmap1->:{aaa=ccc, bbb=bbb}
    중복 키 가 나타 날 때 대응 하 는 value 를 연결 합 니 다.
    
    ...
    Map<String, String> nmap1 = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName, SdsTest::getAge, (k1, k2) -> k1 + "," + k2));
    System.out.println("nmap1->:" + nmap1.toString());
    ...
    ----------------
      :
    nmap1->:{aaa=aaa,ccc, bbb=bbb}
    반복 키 의 값 을 집합 으로 맞 춥 니 다.
    
    ......
    Map<String, List<String>> map = sdsTests.stream().collect(Collectors.toMap(SdsTest::getName,
        s -> {
            List<String> ages = new ArrayList<>();
            ages.add(s.getAge());
            return ages;
        },
        (List<String> v1, List<String> v2) -> {
            v1.addAll(v2);
            return v1;
        }));
    System.out.println("map->"+map.toString());
    ------------
      :
    map->{aaa=\[aaa, ccc\], bbb=\[bbb\]}
    건의:
  • 우선 업무 통제,리스트 에 중복 되 지 않도록 한다
  • 4.567917.중복 장면 이 존재 하면 실제 업무 장면 에 따라 구체 적 인 방법[커버,연결,집합]을 선택한다이상 은 자바 8 에서 Stream 을 사용 하여 List 를 맵 으로 전환 시 키 는 데 총 결 된 상세 한 내용 입 니 다.자바 8 List 를 맵 으로 전환 하 는 데 사용 되 는 자 료 는 저희 의 다른 관련 글 을 주목 하 시기 바 랍 니 다!

    좋은 웹페이지 즐겨찾기