코더가 되고싶은 남자

java stream groupingBy() 리스트 데이터를 그룹핑하여 재가공 본문

java

java stream groupingBy() 리스트 데이터를 그룹핑하여 재가공

guney 2021. 1. 18. 15:03
반응형

오늘도 ~ 언젠가 ~ 웹 프로젝트 시 조회성 api 리스트 데이터를 재가공 해야할 날이 올 것이다.

 

자바에서 리스트 데이터를 재가공하는 일은 아주 비번히 일어난다.

 

항상 쌍 foreach를 돌려 데이터를 새로 SET 하지만 이번에는 스트림 람다식을 이용하여 재가공을 했다.

 

 

- 우선 api로 sellect해온 값으로 가정한 어느 옵션속성 데이터 이다. -

 

[
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 17,
                "optValNm": "F",
                "optDesc": null,
                "mrkRnk": 1,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 18,
                "optValNm": "XL",
                "optDesc": null,
                "mrkRnk": 2,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 19,
                "optValNm": "L",
                "optDesc": null,
                "mrkRnk": 3,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 20,
                "optValNm": "M",
                "optDesc": null,
                "mrkRnk": 4,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 21,
                "optValNm": "S",
                "optDesc": null,
                "mrkRnk": 5,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 29,
                "optNm": "SIZE",
                "optTp": "사이즈",
                "useYn": "Y",
                "optValNo": 22,
                "optValNm": "XS",
                "optDesc": null,
                "mrkRnk": 6,
                "regDtime": "2021-01-12T07:26:27.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-12T07:26:27.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            },
            {
                "optNo": 30,
                "optNm": "test",
                "optTp": "test1",
                "useYn": "Y",
                "optValNo": 0,
                "optValNm": null,
                "optDesc": null,
                "mrkRnk": 0,
                "regDtime": "2021-01-13T06:24:58.000+0000",
                "regrId": null,
                "regrNm": null,
                "modDtime": "2021-01-13T06:24:58.000+0000",
                "modrId": null,
                "modrNm": null,
                "optValItems": null,
                "type": null
            }
 ]

 

 

여기서 optNo 별로 그룹을 지어 optValItems 변수명으로 그룹핑된 데이터를 SET 하고 싶다.

 

아래 코드를 보라

//목업 데이터
String test = "[{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':17,'optValNm':'F','optDesc':null,'mrkRnk':1,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':18,'optValNm':'XL','optDesc':null,'mrkRnk':2,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':19,'optValNm':'L','optDesc':null,'mrkRnk':3,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':20,'optValNm':'M','optDesc':null,'mrkRnk':4,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':21,'optValNm':'S','optDesc':null,'mrkRnk':5,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':29,'optNm':'SIZE','optTp':'사이즈','useYn':'Y','optValNo':22,'optValNm':'XS','optDesc':null,'mrkRnk':6,'regDtime':'2021-01-12T07:26:27.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-12T07:26:27.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null},{'optNo':30,'optNm':'test','optTp':'test1','useYn':'Y','optValNo':0,'optValNm':null,'optDesc':null,'mrkRnk':0,'regDtime':'2021-01-13T06:24:58.000+0000','regrId':null,'regrNm':null,'modDtime':'2021-01-13T06:24:58.000+0000','modrId':null,'modrNm':null,'optValItems':null,'type':null}]";

//쥐쓴 >ㅅ<
Gson gson = new Gson();

//제이슨 파싱
List<Map<String, String>> optionInfoList = gson.fromJson(test, new TypeToken<List<Map<String, String>>>() {}.getType());

//리스트 데이터 스트림
List<Map<String, Object>> optionInfoGroupList = optionInfoList.stream()
		.collect(Collectors.groupingBy((v) -> v.get("optNo")))		//optNo로 그룹핑
		.entrySet().stream()						//그룹핑 후, 키 밸류 값 추출하기 위해 EntraySet 
		.map(v -> {
				Map<String, Object> map = new HashMap<>();
				map.put("optNo", v.getKey());			//내가 원하는 키 밸류 값으로 가공
				map.put("optNm", v.getValue().get(0).get("optNm"));
				map.put("optValItems", v.getValue());
				
				return map;
			})
		.collect(Collectors.toList());

log.info(optionInfoGroupList.toString());

 

해당 테스트는 mockup 데이터를 하드코딩하고 Json 데이터로 파싱하여 생성하였다.

 

 

중요한 부분은 여기다.

.collect(Collectors.groupingBy((v) -> v.get("optNo")))

.콜렉트 부분에 groupingBy()를 쓰는 순간 리턴 데이터는 Map<String, List<Map<String, Object>>>로 받아야 한다.

 

groupingBy()로 연산 후 { }(오브젝트)에 감싸져서 리턴된다.

 

이를 방지하고 List<Map<String, Object>>로 리턴받기 위하여 entraSet으로 재가공을 실시한다!

.entrySet().stream()						//그룹핑 후, 키 밸류 값 추출하기 위해 EntraySet 

 

entrySet().stream()으로 v 데이터가 하나씩 돌면서,  .map() 연산을 통하여 내가 리턴하고자 하는 map데이터의 형식을 입력해준다. 

.map(v -> {
		Map<String, Object> map = new HashMap<>();
		map.put("optNo", v.getKey());			//내가 원하는 키 밸류 값으로 가공
		map.put("optNm", v.getValue().get(0).get("optNm"));
		map.put("optValItems", v.getValue());
		
		return map;
	})
.collect(Collectors.toList());

 

그후 마지막  .collect(Collectors.toList()); 를 통하여, 최종 가공된 List 데이터로 리턴을 시켜주는 것이다.

 

 

- 재가공된 List 데이터 결과 값 -

[
  {
    optNm=SIZE,
    optNo=29,
    optValItems=[
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=17,
        optValNm=F,
        optDesc=null,
        mrkRnk=1,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      },
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=18,
        optValNm=XL,
        optDesc=null,
        mrkRnk=2,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      },
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=19,
        optValNm=L,
        optDesc=null,
        mrkRnk=3,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      },
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=20,
        optValNm=M,
        optDesc=null,
        mrkRnk=4,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      },
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=21,
        optValNm=S,
        optDesc=null,
        mrkRnk=5,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      },
      {
        optNo=29,
        optNm=SIZE,
        optTp=사이즈,
        useYn=Y,
        optValNo=22,
        optValNm=XS,
        optDesc=null,
        mrkRnk=6,
        regDtime=2021-01-12T07: 26: 27.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-12T07: 26: 27.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      }
    ]
  },
  {
    optNm=test,
    optNo=30,
    optValItems=[
      {
        optNo=30,
        optNm=test,
        optTp=test1,
        useYn=Y,
        optValNo=0,
        optValNm=null,
        optDesc=null,
        mrkRnk=0,
        regDtime=2021-01-13T06: 24: 58.000+0000,
        regrId=null,
        regrNm=null,
        modDtime=2021-01-13T06: 24: 58.000+0000,
        modrId=null,
        modrNm=null,
        optValItems=null,
        type=null
      }
    ]
  }
]

 

위 처럼 같은 optNo 별로 optValItems변수명에 List데이터가 그룹핑 된것을 볼 수 있다.

 

맨날 포이치 포이치 인생은 foreach였지만, stream 람다식을 이용하여 머리가 지끈거리는 foreach를 벗어 날 수 있었다.

 

하지만 실전에서 사용한적은 없다. ㅋㅋㅋ

 

ㅎ ㅏ 글이 길어지니까 T스토리 귀찮네,.