스트림에 대해 공부하던중 몇몇 유용해보이는 메서드들이 있어 이에대해 포스팅하게 됬다.
orElse()
List<Integer> list = Arrays.asList();
// 컴파일 오류 발생
Double value = list.stream()
.mapToDouble((a)->a)
.average();
// 런타임 오류 발생
Double value = list.stream()
.mapToDouble((a)->a)
.average()
.getAsDouble();
위와 같은 코드를 작성하면 컴파일 에러가 발생한다. 이유는 average()를 이용해 평균값을 구할때 입력값이 아예 없으면 즉 빈 리스트를 불러와 평균값을 구할수가 없기 때문이다. 해당 리스트에 숫자형 데이터 "0"이라도 존재 한다면 "0"을 리턴하지만 빈 리스트에서는 "0"조차도 값을 구할수 없기 때문이다.
하지만 orElse()메서드를 사용하면 해결된다.
Double value = list.stream()
.mapToDouble((a)->a)
.average()
.orElse(0);
orElse()를 이용하여 값이 아예 없는 '무' 가 될경우 0이라는 기본값을 주도록 설정할수 있다.
Comparable, Comparator 클래스
public class Main {
public static void main(String[] args) {
List<Human> list = Arrays.asList(
new Human("qwe",23),
new Human("asd",24),
new Human("zxc",21),
new Human("rty",23),
new Human("fgh",23)
);
// 객체 안, 문자형 정렬
list.stream()
.sorted(Comparator.comparing((obj)->obj.getName()))
.sorted(Comparator.comparing(Human::getName).reversed()); // 위와 같은 표현식이지만 reversed()메서드로 역순정렬
list.stream()
.sorted((obj1,obj2)->obj2.getName().compareTo(obj1.getName()));
//compareTo를 활용한 역순정렬 이며
//해당 객체의 클래스(Human)에 Comparable클래스를 상속받아
//직접 compareTo메서드를 오버라이딩해줄수도 있다.
}
}
class Human {
private String name;
private int age;
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
굳이 Stream이 아니어도 모든 정렬 메서드에서 사용이 가능하며, 숫자형 데이터는 더 쉬우므로 생략...
Collectors.groupingBy
.collect(Collectors.groupingBy())
groupingBy 메서드를 활용하면 데이터들을 그룹화하여 Map으로 타입을 변환시켜준다.
( .collect()메서드는 해당 데이터들을 담을 컬렉션이나 맵으로 변환할때 사용한다.)
public class Main {
public static void main(String[] args) {
//데이터 리스트
List<Human> list = new ArrayList<>();
list.add( new Human("김철수",23,"남자"));
list.add( new Human("이영희",24,"여자"));
list.add(new Human("개똥이",21,"남자"));
list.add( new Human("박대기",23,"남자"));
list.add( new Human("김세희",23,"여자"));
// 사람들의 나이를 기준으로key를 생성하고 분류하여 해당 나이에 맞는 객체들을 묶어줌
Map<Integer,List<Human>> groupingBy = list.stream().collect(Collectors.groupingBy((a)->a.getAge()));
// grouping된 데이터를 출력하기위해 Set으로 타입 변환(Map 타입으로는 stream불가)
Set<Map.Entry<Integer,List<Human>>> entrySet = groupingBy.entrySet();
// 위의 데이터 Set을 이용하여 스트림을 생성하고 각 아이템들에 접근한뒤 출력
entrySet.stream().forEach((entry)->{
System.out.printf("Entry { Key = %s, Values = ",entry.getKey());
entry.getValue().forEach((a)->a.print());
System.out.println("}");
});
}
}
class Human {
private String name;
private int age;
private String gender;
public Human(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() { return name;}
public String getGender() { return gender; }
public int getAge() { return age; }
public void print(){
System.out.printf("[ name: %s, age: %d, gender: %s ], ", this.name, this.age, this.gender);
}
}
보통 HashMap등 데이터 Map을 만들때는 각 데이터가 가지고 있는 고유한 값을 Key로 사용하지만 groupBy의 경우 이름 그대로 데이터들을 하나의 기준에 맞게 묶어주는 역할을 하기에 각 데이터들이 가지고 있는 값들중 고유하지 않은, 즉 중복된 특정한 값을 Key로 사용해준다.
Grouping을 위한 스태틱메서드생성
public class Main {
public static void main(String[] args) {
List<Human> list = new ArrayList<>();
list.add( new Human("김철수",23,"남자"));
list.add( new Human("이영희",24,"여자"));
list.add(new Human("개똥이",21,"남자"));
list.add( new Human("박대기",23,"남자"));
list.add( new Human("김세희",23,"여자"));
Map<Integer,List<Human>> groupingBy = Mapping.groupingBy(list, Mapping.Options.NAME);
Set<Map.Entry<Integer,List<Human>>> entrySet = Mapping.entrySet(groupingBy);
Mapping.print(entrySet);
}
}
class Mapping{
enum Options {AGE,NAME,GENDER}
private static Options category;
public static Map groupingBy(List<Human> list, Options option){
category = option;
return list.stream().collect(Collectors.groupingBy((a)->{
if(option.equals(Options.NAME)) return a.getName();
if(option.equals(Options.GENDER)) return a.getGender();
return a.getAge();
}));
}
public static Set entrySet(Map<Integer,List<Human>> groupingBy){
return groupingBy.entrySet();
}
public static void print(Set<Map.Entry<Integer,List<Human>>> entrySet){
System.out.printf("Map groupingBy %s {\n",category);
entrySet.stream().forEach((entry)->{
System.out.printf("Entry { Key = %s, Values = ",entry.getKey());
entry.getValue().forEach((a)->a.print());
System.out.println("}");
});
System.out.println("}");
}
}
위와 같이 grouping을 위한 클래스와 스태틱 메서드들을 만들어 보던중 궁금한 것들이 생겨서 실험을 해보던중 몇가지를 알게되었다.
(다음 포스트에 계속...)
'Java > Java' 카테고리의 다른 글
스레드 (Thread) (0) | 2023.03.12 |
---|---|
자바 가상 머신(Java Virtual Machine) (0) | 2023.03.11 |
스트림 (Stream) (0) | 2023.03.10 |
파일 입출력 (InputStream, OuputStream, FileReader, FileWriter, File) (0) | 2023.03.09 |
람다(Lambda) (2) | 2023.03.09 |