java stream groupingBy() 리스트 데이터를 그룹핑하여 재가공
오늘도 ~ 언젠가 ~ 웹 프로젝트 시 조회성 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스토리 귀찮네,.