마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

RxJava 연산자 질문 groupBy

0 추천
Observable.just(
                "A1", "B1", "B2",
                "A2", "C1", "C2",
                "A3", "B3", "C3")
                .groupBy(item->{
                    if(item.contains("A")){
                        return "A 그룹";
                    }
                    else if(item.contains("B")){
                        return "B 그룹";
                    }
                    else if(item.contains("C")){
                        return "C 그룹";
                    }
                    else{
                        return "None";
                    }
                }).subscribe(g->{
            System.out.println(g.getKey()+" 발행");
            g.subscribe(System.out::println);
        });

2022-11-08 18:58:01.066 8913-8913/com.psw.rxtest3 I/System.out: A 그룹 발행
2022-11-08 18:58:01.066 8913-8913/com.psw.rxtest3 I/System.out: A1
2022-11-08 18:58:01.066 8913-8913/com.psw.rxtest3 I/System.out: B 그룹 발행
2022-11-08 18:58:01.066 8913-8913/com.psw.rxtest3 I/System.out: B1
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: B2
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: A2
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: C 그룹 발행
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: C1
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: C2
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: A3
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: B3
2022-11-08 18:58:01.067 8913-8913/com.psw.rxtest3 I/System.out: C3
 

이러한 결과가 나오는데 제가 생각한 결과는 

A그룹에 A1,A2,A3

B그룹에 B1,B2,B3

C그룹에 C1,C2,C3 라고 생각했는데 다른 결과가 나옵니다. 왜그런건가요?

 

 

 

개미1 (1,260 포인트) 님이 2022년 11월 8일 질문

1개의 답변

0 추천

Rxjava를 써 본지가 너무 오래되어서 기억이 가물가물한데, 찾아보니

https://reactivex.io/documentation/operators/groupby.html

RxJava는 스트림으로 동작을 하므로, groiupBy를 통해 님이 생각하는 상태의 값을 얻으려면 groupBy 후에 정렬된 상태가 되도록 collect를 해주어야 합니다.

아래처럼 groupBy 후에, flatMap을 통해 collect해주는 과정이 필요합니다.

List<String> whiteListedGroup = Arrays.asList("A", "B", "C");
Observable.just(
      "A1", "B1", "B2",
     "A2", "C1", "C2",
      "A3", "B3", "C3")
  .groupBy(item -> {
         String groupName = item.substring(0, 1);
         return whiteListedGroup.contains(groupName) ? groupName : "None";
   })
  .flatMapSingle(f -> f.collect(
          // (Callable<Map<String, List<String>>>)
           () -> Collections.singletonMap(f.getKey(), new ArrayList<String>()),
           // (BiConsumer<Map<String, List<String>>, String>)
           (m, s) -> m.get(f.getKey()).add(s)
  ))
  .subscribe(g -> {
         System.out.println(g);
   });            

단순히 colletion을 가지고 groupBy를 할거라면 Java8의 stream api가 더 합리적인 선택이지만, 네트워크 호출 같은 걸 해야 한다면, RxJava를 통하는 것이 더 적합한 것 같습니다.

spark (226,420 포인트) 님이 2022년 11월 8일 답변
...