Stream의 collect 매소드는 위와 같이 정의되어 있습니다.
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
...
}
StringBuilder sbResult= Stream.<String>builder()
.add("je")
.add("r")
.add("ry")
.add("st")
.add("udy")
.build()
.collect(StringBuilder::new,
// [Supplier<R> supplier]. ()-> new StringBuilder()로 StringBuilder 객체 생성
(sb, word)->sb.append(word),
// [BiConsumer<R, ? super T> accumulator]. Supplier로 생성한 StringBuilder 객체에 Stream 요소들을 append 하는 함수 정의
(sb1,sb2)-> sb1.append(sb2));
// [BiConsumer<R, R> combiner]. 병렬처리시 각 스레드에서 생성된 StringBuilder 객체를 결합
System.out.println(sbResult.toString());
[output]
jerrystudy
Collectors에 정의된 정적 매소드들을 활용하면 collect 함수를 쉽게 구현할 수 있습니다.
Stream<String> stream= Arrays.asList("0.342","1.234","12.23","0.23").stream();
Double avgDouble=stream.collect(Collectors.averagingDouble(val-> Double.valueOf(val)));
System.out.println("avg Double : "+avgDouble);
static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
: Collector를 이용해 변환한 후 추가적인 변환작업을 한번 더 하는 경우 사용
Map<String, String> immutableMap = Stream.of(new String[][] {})
.collect(Collectors.collectingAndThen(
Collectors.toMap(p -> p[0], p -> p[1]),
Collections::<String, String>unmodifiableMap
));
static <T> Collector<T,?,Long> counting()
: Stream 요소의 갯수를 카운트하여 Long 타입으로 리턴
static <T,K> Collector<T,?,Map<K,List>> groupingBy(Function<? super T,? extends K> classifier)
: Stream 요소를 특정 기준으로 분류하여, 분류 기준을 key로 해당되는 요소를 List형태 value로 Map객체 생성
// Car.java
public class Car {
private int price;
private String carName;
...
}
// Person.java
public class Person {
String name;
int age;
Car car;
...
}
//test 코드
Person person1=new Person("jerry",10,new Car(1000,"avante"));
Person person2=new Person("tom",20,new Car(2000,"audi"));
Person person3=new Person("ford",30,new Car(3000,"toycar"));
Person person4=new Person("leli",15,new Car(1000,"avante"));
Person person5=new Person("amy",40,new Car(5000,"toycar"));
List<Person> lists=new ArrayList<>();
lists.add(person1);
lists.add(person2);
lists.add(person3);
lists.add(person4);
lists.add(person5);
Map<String,List<Person>> groups = lists.stream().collect(Collectors.groupingBy(person -> person.getCar().getCarName()));
for(Map.Entry<String,List<Person>> entry : groups.entrySet()){
System.out.println("key : "+ entry.getKey());
System.out.println("value : "+ entry.getValue());
}
[output]
key : toycar
value : [Person{name='ford', age=30, car=Car{price=3000, carName='toycar'}}, Person{name='amy', age=40, car=Car{price=5000, carName='toycar'}}]
key : avante
value : [Person{name='jerry', age=10, car=Car{price=1000, carName='avante'}}, Person{name='leli', age=15, car=Car{price=1000, carName='avante'}}]
key : audi
value : [Person{name='tom', age=20, car=Car{price=2000, carName='audi'}}]
static Collector<CharSequence,?,String> joining()
: String Stream인 경우 String들을 연결해서 하나의 String으로 반환
[유사매소드]
static Collector<CharSequence,?,String> joining(CharSequence delimiter)
: Stream 요소를 연결할때 구분자를 중간에 삽입 delimiter
static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
: Stream 요소 연결할때 앞(prefix), 뒤(suffix)로 문자열을 붙인 후 delimiter 구분자로 연결
static <T,U,A,R> Collector<T,?,R> mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)
: Stream 요소를 mapper 함수로 변환한 후 downstream 함수를 이용해 다른 형태로 변환후 리턴
static <T> Collector<T,?,Optional> maxBy(Comparator<? super T> comparator)
: 주어진 comparator 함수를 이용해 Stream 요소 중 max 요소를 Optional로 랩핑 하여 리턴
static <T> Collector<T,?,Optional> minBy(Comparator<? super T> comparator)
: 주어진 comparator 함수를 이용해 Stream 요소 중 min 요소를 Optional로 랩핑 하여 리턴
static <T> Collector<T,?,Map<Boolean,List>> partitioningBy(Predicate<? super T> predicate)
: predicate 함수식으로 stream 요소에 대한 논리연산 결과값을 리턴하여, 결과값 true/false를 key로 Map 객체 생성
Stream<Integer> stream3=Arrays.asList(1,2,3,4,5,6,7,8,9,10).stream();
Map<Boolean, List<Integer>> collect = stream3.collect(Collectors.partitioningBy(val -> val % 2 == 0));
for(Map.Entry<Boolean,List<Integer>> entry : collect.entrySet()){
System.out.println("key : "+ entry.getKey());
System.out.println("value : "+ entry.getValue());
}
[output]
key : false
value : [1, 3, 5, 7, 9]
key : true
value : [2, 4, 6, 8, 10]
Stream<Integer> stream=Arrays.asList(1,2,3,4,5,6,7,8,9,10).stream();
Integer accumulateSum=stream.collect(Collectors.reducing
(0, // 초기값
Integer::intValue // mapper. Stream의 요소를 mapper를 통해 변환
,(total, num)->total+num)); // total은 축적되는 값, num은 mapper로 변환된 Stream의 요소
System.out.println("reducing result: "+ accumulateSum);
[output]
reducing result: 55
static <T> Collector<T,?,Double> summingDouble(ToDoubleFunction<? super T> mapper)
: mapper함수로 Stream 요소를 Double 타입으로 변환 후 합계를 구하여 Double 타입으로 리턴
static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)
: Stream 요소를 mapper함수로 Double로 변환후 요소들의 DoubleSummaryStatistics 객체를 생성
package java.util;
public class DoubleSummaryStatistics implements DoubleConsumer {
private long count;
private double sum;
private double sumCompensation; // Low order bits of sum
private double simpleSum; // Used to compute right sum for non-finite inputs
private double min = Double.POSITIVE_INFINITY;
private double max = Double.NEGATIVE_INFINITY;
...
public final long getCount() {
return count;
}
public final double getSum() {
...
}
public final double getMin() {
return min;
}
public final double getMax() {
return max;
}
public final double getAverage() {
return getCount() > 0 ? getSum() / getCount() : 0.0d;
}
[유사매소드]
static <T,C extends Collection>
Collector<T,?,C> toCollection(Supplier collectionFactory)
: Collection 인터페이스를 구현한 특정 객체로 변환하여 리턴 [toSet(), toList()의 경우에는 특정한 구현 객체 지정 불가]
static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
: Stream의 요소와 key를 추출하는 함수, value를 추출하는 함수를 정의하여 Map객체를 반환
static Collector<T,?,List> toList()
: Stream 요소를 List 형태로 리턴
static <T> Collector<T,?,Set> toSet()
: Stream의 요소를 Set 데이터 타입으로 변환
[참고]
Java Stream 사용자 정의 컨테이너에 수집하기(collect())
techie delight - Collectors collectingAndThen() method in Java