자바8(7)--Stream(중) 배우러 왔어요.
Java8( )——Stream( )
에서 우리는 Stream 대상의 상용 방법과 용법을 알게 되었다.지금부터 Stream.collect()
방법의 사용을 깊이 있게 알아보겠습니다.collect 기본 사용법
collect는 수집을 의미합니다. 이것은 Stream의 요소를 수집하고 귀납하여 새로운 집합 대상을 되돌려줍니다.먼저 간단한 예를 살펴보겠습니다.
public class CollectTest {
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
private int price;
}
public static void main(String[] args) {
List list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
List nameList = list.stream()
.map(Goods::getGoodsName)
.collect(Collectors.toList());
}
}
이 예에서 맵 방법을 통해 상품 이름을 되돌려주고 모든 상품 이름을 리스트 대상에 넣는다.
원본 코드를 보면collect 방법은 두 가지 재부팅 방법으로 구성되어 있습니다.
R collect(Supplier supplier,
BiConsumer accumulator,
BiConsumer combiner);
R collect(Collector super T, A, R> collector);
그 중에서 가장 많이 사용하는 방법은 방법2이다. 이 방법은 방법1의 빠른 방식이라고 볼 수 있다. Collector에서 똑같이
Supplier supplier, BiConsumer accumulator, BiConsumer combiner
라는 세 개의 매개 변수를 제공했기 때문에 그 밑바닥은 방법1에 대응하는 실현을 사용해야 한다고 추측하기 어렵지 않다.우리는 먼저
collect(Collector super T, A, R> collector)
부터 시작해서 이것을 통해 방법 1의 용법을 천천히 이해할 수 있다.Collectors
Stream.collect(Collector super T, A, R> collector)
방법의 매개 변수인 콜렉터 대상은 주로 Collectors
류에서 제공한다.Collectors 클래스에는 다음과 같은 방법으로 Collector 객체를 반환하는 일련의 정적 방법이 포함되어 있습니다.메서드 이름
묘사
averagingXX
평균을 구하다
counting
집합 중의 원소 개수를 구하다
groupingBy
컬렉션 그룹화
joining
집합 원소를 조립하다
mapping
그룹을 나누는 과정에서 값을 다시 매핑할 수 있습니다
maxBy
최대치를 구하다
minBy
최소값을 구하다
partitioningBy
요소 분할
reducing
귀납
summarizingXX
한데 모으다
toCollection
컬렉션 객체로 변환
toConcurrentMap
ConcurrentMap으로 변환
toList
List로 변환
toMap
맵으로 변환
toSet
셋으로 변환
다음은 순서대로 각 방법의 용도를 설명한다.
averagingXX
averagingXX에는 averagingDouble, averagingInt, averagingLong이 포함됩니다.그것들은 평균치를 구하는 것을 나타낸다.
double averagingInt = Stream.of(1, 2, 3)
.collect(Collectors.averagingInt(val -> val));
System.out.println("averagingInt:" + averagingInt);
double averagingLong = Stream.of(10L, 21L, 30L)
.collect(Collectors.averagingLong(val -> val));
System.out.println("averagingLong:" + averagingLong);
double averagingDouble = Stream.of(0.1, 0.2, 0.3)
.collect(Collectors.averagingDouble(val -> val));
System.out.println("averagingDouble:" + averagingDouble);
이러한 매개 변수는 Lambda 표현식으로 작성할 수 있는 함수식 인터페이스로, 여기서 Lambda 표현식의 매개 변수는 Stream의 요소이고 평균 수치를 반환합니다.아래의 이 열은 상품의 평균치를 구하는 것이다.
List list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
double avgPrice = list.stream()
.collect(Collectors.averagingInt(goods -> goods.getPrice()));
System.out.println(" :" + avgPrice);
summingXX
averagingXX와 유사하게,summingXX 방법은 집합 중의 원소 값의 총계를 구하는 데 사용된다.
double summingInt = Stream.of(1, 2, 3)
.collect(Collectors.summingInt(val -> val));
System.out.println("summingInt:" + summingInt);
double summingLong = Stream.of(10L, 21L, 30L)
.collect(Collectors.summingLong(val -> val));
System.out.println("summingLong:" + summingLong);
double summingDouble = Stream.of(0.1, 0.2, 0.3)
.collect(Collectors.summingDouble(val -> val));
System.out.println("summingDouble:" + summingDouble);
인쇄:
summingInt:6.0
summingLong:61.0
summingDouble:0.6
counting()
counting () 은 집합의 원소 개수를 되돌려줍니다.
long count = Stream.of(1,2,3,4,5)
.collect(Collectors.counting());
System.out.println("count:" + count); // 5
summarizingXX
위에서 말했듯이averagingXX(평균을 구하라),summingXX(화합을 구하라),counting(총수를 구하라),만약 내가 이 세 개의 수를 동시에 얻으려면 어떻게 해야 합니까?summarizingXX를 사용할 수 있습니다.
IntSummaryStatistics summarizingInt = Stream.of(1, 2, 3)
.collect(Collectors.summarizingInt(val -> val));
System.out.println(" :" + summarizingInt.getAverage());
System.out.println(" :" + summarizingInt.getCount());
System.out.println(" :" + summarizingInt.getSum());
System.out.println(" :" + summarizingInt.getMax());
System.out.println(" :" + summarizingInt.getMin());
인쇄:
:2.0
:3
:6
:3
:1
summarizingInt는 통계 결과를 IntSummaryStatistics 대상에 넣고 대상에서 서로 다른 통계 정보를 얻을 수 있습니다.
groupingBy()
groupingBy () 는 집합의 원소를 그룹으로 나누어 세 가지 재부팅 방법으로 구성한다
우선 재부팅 1
groupingBy(Function)
의 사용법을 살펴보자. 이 방법은 기본적으로 새로운List에 그룹을 나눈다. 아래의 예는 상품 유형을 그룹으로 나누고 같은 유형의 상품을 하나의List에 놓는다.@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
// ,1: ,2:
private int type;
@Override
public String toString() {
return goodsName;
}
}
public static void main(String[] args) {
List list = Arrays.asList(
new Goods("iphoneX", 1)
, new Goods("mate30 pro", 1)
, new Goods("thinkpad T400", 2)
, new Goods("macbook pro", 2)
);
Map> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType));
goodsListMap.forEach((key, value) -> {
System.out.println(" " + key + ":" + value);
});
}
인쇄:
1:[iphoneX, mate30 pro]
2:[thinkpad T400, macbook pro]
위에서 말한 바와 같이
groupingBy(Function)
는 실제로 호출되었다groupingBy(Function, Collector)
. 그 중에서 두 번째 파라미터Collector
는 어디로 전환할 것인지를 결정했다. 기본값은 toList()
이다. 참조groupingBy(Function)
의 원본 코드:public static Collector>>
groupingBy(Function super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
따라서 우리는
groupingBy(Function, Collector)
를 호출해서 수동으로 Collector를 지정할 수 있다. 변환된 요소를 Set에 넣으려면 이렇게 쓸 수 있다.Map> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType, Collectors.toSet()));
재부팅 2 메소드 소스를 살펴보면 재부팅 3이 호출된 것입니다.
public static
Collector> groupingBy(Function super T, ? extends K> classifier,
Collector super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
그 중에서
Goods::getType
는classifier에 대응하고 Collectors.toSet()
는downstream에 대응한다.중간에 있는 매개 변수HashMap::new
는 의미가 뚜렷하다. 즉, 되돌아오는 맵의 구체적인 실현 클래스가 무엇인지, 링크드 해시 맵으로 바꾸려면 이렇게 쓸 수 있다.LinkedHashMap> goodsListMap = list.stream()
.collect(Collectors.groupingBy(Goods::getType, LinkedHashMap::new, Collectors.toSet()));
이것이 바로 중재 3의 사용 방식이다.
Collectors의 groupingByConcurrent 방법은 바로 재부팅 3을 기반으로 한 것이고 중간 코드는
ConcurrentHashMap::new
로 바뀌었을 뿐이다.public static
Collector>>
groupingByConcurrent(Function super T, ? extends K> classifier) {
return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
}
GroupingBy 방법의 Collector 매개 변수는 toList(), toSet()만 사용할 수 있는 것이 아니라 더욱 유연한 사용법도 있다. 이전에 우리가 전환한 것은 모두
Map>
형식이고value에 저장된 것은 집합 대상이다. 그렇게 많은 속성을 원하지 않으면 대상 안의 상품 이름만 원한다. 즉, 우리가 얻고 싶은 것은 Map>
이다. 그 중에서 키는 상품 유형이고value는 상품 이름 집합이다.이때
Collectors.mapping()
가 도움이 되었습니다. 우리는 groupingBy(Function, Collector)
방법을 사용했고 두 번째 매개 변수 전송Collectors.mapping()
을 사용했습니다.Map> goodsListMap =
list.stream()
.collect(
Collectors.groupingBy(
Goods::getType,
Collectors.mapping(Goods::getGoodsName, Collectors.toList())
)
);
mapping () 방법은 두 개의 매개 변수가 있는데, 첫 번째 매개 변수는 되돌아오는 속성을 지정하고, 두 번째 매개 변수는 어떤 집합을 되돌아오는지 지정합니다.
joining
joining 방법은Stream의 요소를 연결할 수 있습니다.
List list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining());
System.out.println(str); // :helloworld
구분자를 지정할 수도 있습니다.
List list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining(","));
System.out.println(str); // :hello,world
이외에
String
류는 하나의join방법을 제공했는데 기능은 같다String str2 = String.join(",", list);
System.out.println(str2);
maxBy&minBy
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
private int price;
}
public static void main(String[] args) {
List list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
Goods maxPriceGoods = list.stream()
.collect(
Collectors.maxBy(
Comparator.comparing(Goods::getPrice)
)
)
.orElse(null);
System.out.println(" :" + maxPriceGoods);
}
위의 예는 가장 비싼 상품을 찾는 것을 보여 준다. Collectors.maxBy() 방법은 비교기를 전송해야 하며 상품의 가격에 따라 비교해야 합니다.
마찬가지로 가장 싼 상품을 찾으면
maxBy
를 minBy
로 바꾸면 된다.partitioningBy
파티션 By 방법은 섹션을 나타낸다. 조건에 따라 Stream의 요소를 두 부분으로 나누어 각각 하나의 맵에 넣는다. 맵의 키는 Boolean 유형이고 키는true 부분은 조건에 맞는 요소를 저장하고 키는false는 조건에 부합되지 않는 요소를 저장한다.
{
true ->
false ->
}
partitioningBy 메서드는 두 가지 재로드 메서드로 구성됩니다.
다음 예는 상품 유형에 따라 상품을 휴대전화 상품과 비휴대전화 상품으로 나눈다.
@Data
@AllArgsConstructor
static class Goods {
private String goodsName;
// ,1: ,2:
private int type;
@Override
public String toString() {
return goodsName;
}
}
public static void main(String[] args) {
List list = Arrays.asList(
new Goods("iphoneX", 1)
, new Goods("mate30 pro", 1)
, new Goods("thinkpad T400", 2)
, new Goods("macbook pro", 2)
);
// ,
// true ->
// false ->
Map> goodsMap = list.stream()
.collect(
Collectors.partitioningBy(goods -> goods.getType() == 1)
);
//
List mobileGoods = goodsMap.get(true);
System.out.println(mobileGoods);
}
partitioningBy(Predicate,Collector) 방법의 두 번째 인자는 집합 요소를 지정할 수 있습니다. 기본적으로 사용하는List 저장은 Set 저장을 사용하려면 다음과 같이 쓸 수 있습니다.
Map> goodsMap = list.stream()
.collect(
Collectors.partitioningBy(
goods -> goods.getType() == 1
//
, Collectors.toSet())
);
toList & toSet & toCollection
toList와 toSet은 Stream의 원소를 List, Set 집합으로 변환할 수 있는데 이것은 비교적 많이 사용하는 두 가지 방법이다.
Stream stream = Stream.of(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
List list = stream.collect(Collectors.toList());
Set set = stream.collect(Collectors.toSet());
기본적으로 ToList는 Array List를 되돌려줍니다. ToSet은 HashSet을 되돌려줍니다. 링크드 List와 같은 다른 종류의 집합을 되돌려받으려면
toCollection
을 사용할 수 있습니다. 개발자가 어떤 집합이 필요한지 지정할 수 있습니다.LinkedList linkedList = stream.collect(Collectors.toCollection(LinkedList::new));
toConcurrentMap
toConcurrentMap 방법은 Stream을 ConcurrentMap으로 변환하는 것입니다. 세 가지 재부팅 방법으로 구성됩니다.
toConcurrentMap(Function super T, ? extends K> keyMapper, Function super T, ? extends U> valueMapper)
toConcurrentMap(Function super T, ? extends K> keyMapper, Function super T, ? extends U> valueMapper, BinaryOperator mergeFunction)
toConcurrentMap(Function super T, ? extends K> keyMapper, Function super T, ? extends U> valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier)
먼저 재부팅 1을 보고 두 개의 매개 변수를 제공했다
아래의 이 예는 상품의 명칭을 키로 하고 가격을value로 한다
List list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("redmek20", 2999)
);
ConcurrentMap goodsMap = list.stream()
.collect(
Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice)
);
System.out.println(goodsMap);
인쇄:
{mate30 pro=5999, iphoneX=4000, redmek20=2999}
주의: 이 방법은 키가 중복되지 않도록 요구합니다. 만약 중복된 키가 있다면 Illegal State Exception 이상을 던질 것입니다. 키가 중복되면
toConcurrentMap(Function, Function, BinaryOperator)
즉 다시 불러오기 2를 사용해야 합니다.다시 한 번 재부팅 2:
toConcurrentMap(Function, Function, BinaryOperator)
를 살펴보자. 이 방법은 앞의 두 파라미터가 재부팅 1과 같고 세 번째 파라미터는 키 충돌 상황을 처리하기 위해 개발자가value 값을 선택하여 되돌려준다.List list = Arrays.asList(
new Goods("iphoneX", 4000)
, new Goods("mate30 pro", 5999)
, new Goods("mate30 pro", 6000) //
, new Goods("redmek20", 2999)
);
ConcurrentMap goodsMap = list.stream()
.collect(
Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice, new BinaryOperator() {
@Override
public Integer apply(Integer price1, Integer price2) {
//
return Math.max(price1, price2);
}
})
);
System.out.println(goodsMap);
인쇄:
{mate30 pro=6000, iphoneX=4000, redmek20=2999}
이 예에서mate30pro는 키로 중복되었습니다. BinaryOperator
에서 우리는 가격이 높은 데이터를 선택하여 되돌려줍니다.마지막으로 리셋 3을 보십시오. 리셋 2보다 인자가 하나 더 있습니다.
Supplier
개발자가 리셋을 지정할 수 있습니다. ConcurrentMap
리셋 2, 리셋 3 호출, 기본값은 ConcurrentMap::new
입니다.참고: 네 번째 매개변수는 ConcurrentMap 또는 ConcurrentMap의 하위 클래스여야 합니다.
소절
이 글은 주로
Stream.collect
의 용법과 Collectors
류 중의 정적 방법의 사용을 설명했고 다음 글에서는 reduce
에 관한 용법을 상세하게 설명할 것이다.정기적으로 기술 건조품을 공유하고, 함께 공부하고, 함께 진보하자!위챗 공식계정: 원숭이가 달을 치며 번호를 내린다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.