Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- multipart테스트
- aws
- Linux
- ksql
- findTopBy
- javascript case
- #docker compose
- ksqldb
- 백명석님
- intellij favorites
- 자바 ORM 표준 JPA 프로그래밍 정리
- @TransactionalEventListener
- git
- IntelliJ
- @Transactional Propagation
- 마이크로 서비스
- CompletableFuture
- JPA
- vue.js
- 친절한 SQL 튜닝
- Stream
- intellij 핵심 단축키
- intellij 즐겨찾기
- java
- 원격 브랜 삭제
- HandlerMethodArgumentResolver
- 자바 ORM 표준 JPA 프로그래밍
- 리팩토링 2판
- Spring Cloud Netflix
- 리눅스
Archives
- Today
- Total
시그마 삽질==six 시그마
Stream collect 2탄(그룹핑) 본문
해당글은 신용권님의 '이것이 자바다' 를 토대로 작성되었습니다.
예전에 남궁성님의 '자바의 정석' 그리고 신용권님의 '이것이 자바다' 두권 다 보았는데
저는 개인적으로 신용권님의 책이 좀 더 핵심을 찌르고 직관적이어서 좋았던거 같습니다.
책은 요기에서 구매 가능합니다.
요소를 그룹핑해서 수집
collect()메소드는 단순히 요소를 수집하는 기능 외에 컬렉션의 요소들을 그룹핑해서 Map객체를 생성하는 기능도 제공한다
Collectors 의 groupingBy() 또는 groupingByConcurrent()가(쓰레드에 안전) 리턴하는 Collector를 매개값으로 대입하면 된다.
Collectors.groupingBy() 메소드는 그룹핑 후 매핑이나 집계(평균,카운팅,연결,최대,최소합계)를 할 수있도록 두번째 매개값으로 Collector를 가질 수 있다(두번째 매개값으로 인해 기존 value값이 달라진다 ㅎ)
collectors 정적메소드 팁:
toMap(
Function<T,K> keyMapper,
Function<T,U> valueMapper) 이든
groupingBy(Function<T,K> classifier)이든
groupingBy(Function<T,K> classifier,
Collector<T,A,D> collector)이든
첫번째 매개변수의 리턴값이 key다.
두번째 매개변수가 있다면 리턴값이 value다
리턴타입 | Colllectors의 정적메소드 | 설명 |
Collector<T,?,Map<K,List<T>>> | groupingBy(Function<T,K> classifier) | T를 넣어 K를 리턴 최종적으로 K가 key인 value T를 얻는다 ex) 람다:T(매개값 -학생)->K(리턴값-성별) 최종리턴: Key:성별(K) value:학생(T) |
Collector<T,?,ConcurrentMap<K,List<T>>> | groupingByConcurrent( Function<T,K> classifier) |
|
Collector<T,?,Map<K,D>> | groupingBy(Function<T,K> classifier, Collector<T,A,D> collector) |
T를 넣어 K를 리턴하고 T를 넣어 D를 리턴한다 최종적으로 K가 key인 value D를 얻는다 ex) 람다: T(매개값-학생)->K(리턴값-도시) T(매개값-학생)->A->D(리턴값-이름) 최종리턴 Key:도시(K) value:이름(D) |
Collector<T,?,ConcurrentMap<K,D>> | groupingByConcurrent( Function<T,K> classifier, Collector<T,A,D> collector) |
@Data
@AllArgsConstructor
public class Student {
private String name;
private int score;
private Gender gender;
private City city;
public Student(String name, int score, Gender gender) {
this.name = name;
this.score = score;
this.gender = gender;
}
}
@Getter
@AllArgsConstructor
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Gender {
MALE("남자","men")
, FEMALE("여자","woman");
private String korName;
private String engName;
}
public enum City {
Seoul
, Pusan
}
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class GenderDto {
private Gender gender;
private List<Student> students;
}
@Test
public void groupingByExample1() throws Exception{
//given
List<Student> totalList = Arrays.asList(
new Student("공유", 10, Gender.MALE, City.Seoul),
new Student("김태희", 6, Gender.FEMALE, City.Pusan),
new Student("원빈", 10, Gender.MALE, City.Pusan),
new Student("전지현", 6, Gender.FEMALE, City.Seoul)
);
//long
Stream<Student> totalStream = totalList.stream();
Function<Student,Gender> classifier = Student :: getGender;
Collector<Student,?,Map<Gender,List<Student>>> collector = Collectors.groupingBy(classifier);
Map<Gender,List<Student>> mappedByGender=totalStream.collect(collector);
//short
Map<Gender, List<Student>> genderMap = totalList.stream()
//.collect(Collectors.groupingBy(v->v.getGender()));//하단과 같음
.collect(Collectors.groupingBy(Student :: getGender));
System.out.println("mapBySex = " + genderMap);
//mapBySex = {FEMALE=[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)], MALE=[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]}
System.out.print("[남학생] ");
//v -> v.getGender().getEngName() 뿐만아니라 .v.객체.객체 이렇게 들어가도됨!
Map<String, List<Student>> collect1 = totalList.stream().collect(Collectors.groupingBy(v -> v.getGender().getEngName()));
LinkedHashMap<Gender, List<Student>> collect2 = totalList.stream().collect(Collectors.groupingBy(it ->
it.getGender()
, LinkedHashMap::new
, Collectors.toList()
));
//forEach key value로 나눠서 보낼 수 있음
collect2.forEach((gender,StudentList)-> System.out.println("gender:" + gender+" StudentList:"+StudentList));
//gender:MALE StudentList:[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]
//gender:FEMALE StudentList:[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]
genderMap.get(Gender.MALE).stream().forEach(s->System.out.print(s.getName() + " "));
System.out.print("\n[여학생] ");
genderMap.get(Gender.FEMALE).stream().forEach(s->System.out.print(s.getName() + " "));
//[남학생] 공유 원빈
//[여학생] 김태희 전지현
//map 사용법1 (key와 해당 value를 람라로 넘김.v.getValue()는 한개key에 해당하는 리스트임!!!)
List<GenderDto> list = genderMap.entrySet().stream().map(v -> GenderDto.builder().gender(v.getKey()).students(v.getValue()).build())
.collect(Collectors.toList());
System.out.println("\nlist = " + list);
//list = [GenderDto(gender=FEMALE, students=[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]), GenderDto(gender=MALE, students=[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)])]
genderMap.entrySet()/*.stream()*/.forEach(v->System.out.println("\n student = " + v));
//key 와 value 묶여서 출력됨
// student = FEMALE=[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]
// student = MALE=[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]
//map 사용법2(key마다 해당 value만 넘김!! key는 포)
List<GenderDto> list1 = genderMap.values().stream().map(v -> {
System.out.println("v="+v);
return GenderDto.builder().gender(Gender.FEMALE).students(v).build();
}).collect(Collectors.toList());
System.out.println("\nlist1 = " + list1);
//v=[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]
//v=[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]
//list1 = [GenderDto(gender=FEMALE, students=[Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]), GenderDto(gender=FEMALE, students=[Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)])]
genderMap.values()/*.stream()*/.forEach(v-> System.out.println("\n student2 = " + v));
//key 에해당하는 value들만 묶여서 출력됨
// student2 = [Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul)]
// student2 = [Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]
//map 사용법3감(전부 flat시킴)
List<Student> collect = genderMap.values().stream().flatMap(v -> v.stream()).collect(Collectors.toList());
System.out.println("collect = " + collect); //1개씩 결과가 출력
//collect = [Student(name=김태희, score=6, gender=FEMALE, city=Pusan), Student(name=전지현, score=6, gender=FEMALE, city=Seoul), Student(name=공유, score=10, gender=MALE, city=Seoul), Student(name=원빈, score=10, gender=MALE, city=Pusan)]
//map 사용법4( 두 방법으로 사용가능, 그냥사용 or flat)
for(Entry<Gender, List<Student>> entry: genderMap.entrySet()){
final Gender gender = entry.getKey();
final List<Student> students = entry.getValue();
entry.getValue().stream().forEach(v-> System.out.println("map2:"+v));
}
//map2:Student(name=김태희, score=6, gender=FEMALE, city=Pusan)
//map2:Student(name=전지현, score=6, gender=FEMALE, city=Seoul)
//map2:Student(name=공유, score=10, gender=MALE, city=Seoul)
//map2:Student(name=원빈, score=10, gender=MALE, city=Pusan)
}
//하단의 예제는 다음에 이어지는 'Stream collect 3탄(그룹핑후 매핑 및 집계)' 를 봐야 이해가된다
@Test
public void groupingByExample2() throws Exception{
//given
List<Student> totalList = Arrays.asList(
new Student("공유", 10, Gender.MALE, City.Seoul),
new Student("김태희", 6, Gender.FEMALE, City.Pusan),
new Student("원빈", 10, Gender.MALE, City.Pusan),
new Student("전지현", 6, Gender.FEMALE, City.Seoul)
);
//long
Stream<Student> totalStream = totalList.stream();
Function<Student,City> classifier = Student :: getCity;
Function<Student,String> mapper= Student::getName;
Collector<String,?,List<String>> collector1= Collectors.toList();
Collector<Student,?,List<String>> collector2= Collectors.mapping(mapper,collector1);
Collector<Student,?,Map<City,List<String>>> collector3 = Collectors.groupingBy(classifier,collector2);
Map<City,List<String>> mappedByCity=totalStream.collect(collector3);
//short
Map<City, List<String>> mapByCity = totalList.stream()
.collect(
Collectors.groupingBy(
Student::getCity,
Collectors.mapping(Student::getName, Collectors.toList())
)
);
System.out.println("mapByCity = " + mapByCity);
System.out.print("\n[서울] ");
mapByCity.get(City.Seoul).stream().forEach(s->System.out.print(s + " "));
System.out.print("\n[부산] ");
mapByCity.get(City.Pusan).stream().forEach(s->System.out.print(s + " "));
}
결과
mapByCity = {Seoul=[공유, 전지현], Pusan=[김태희, 원빈]}
[서울] 공유 전지현
[부산] 김태희 원빈
@Test
public void groupingByExample0() throws Exception{
List<Student> totalList = Arrays.asList(
new Student("공유", 10, Gender.MALE, City.Seoul),
new Student("김태희", 6, Gender.FEMALE, City.Pusan),
new Student("원빈", 10, Gender.MALE, City.Pusan),
new Student("전지현", 6, Gender.FEMALE, City.Seoul)
);
Map<Gender, Map<String, Map<String, List<Student>>>> collect = totalList.stream()
.collect(Collectors.groupingBy(Student::getGender, Collectors.groupingBy(v -> v.getGender().getKorName(),
Collectors.groupingBy(v -> v.getGender().getEngName()))));
String s = new ObjectMapper().writeValueAsString(collect);
System.out.printf( "JSON: %s", s);
}
{
"MALE": {
"남자": {
"men": [
{
"name": "공유",
"score": 10,
"gender": {
"korName": "남자",
"engName": "men",
"code": "MALE",
"male": true
},
"city": "Seoul"
},
{
"name": "원빈",
"score": 10,
"gender": {
"korName": "남자",
"engName": "men",
"code": "MALE",
"male": true
},
"city": "Pusan"
}
]
}
},
"FEMALE": {
"여자": {
"woman": [
{
"name": "김태희",
"score": 6,
"gender": {
"korName": "여자",
"engName": "woman",
"code": "FEMALE",
"male": false
},
"city": "Pusan"
},
{
"name": "전지현",
"score": 6,
"gender": {
"korName": "여자",
"engName": "woman",
"code": "FEMALE",
"male": false
},
"city": "Seoul"
}
]
}
}
}
'프로그래밍 > Java' 카테고리의 다른 글
java stream grouping() 후 각 그룹별 특정조건에 따라 한개씩만 추출 (0) | 2020.10.30 |
---|---|
Stream collect 3탄(그룹핑후 매핑 및 집계) (0) | 2020.08.27 |
Stream collect 1탄 (0) | 2020.08.27 |
[mac] java 버전 변경 jenv (0) | 2020.08.18 |
java stream 객체 필드로 sorted (0) | 2020.04.20 |
Comments