[JAVA] Stream API 연산 활용

SCY·2023년 1월 31일
0

1️⃣ Stream 생성

Stream API 사용을 위해서는 먼저 Stream을 생성해주어야 한다.
타입에 따라 Stream을 생성하는 방법이 다르다.
그 중 Collection과 Array에 대한 생성 방법을 알아보자.

Collection

Collection 인터페이스에는 stream()이 정의되어 있다.
따라서 List, Set 등의 객체들은 모두 stream()으로 생성할 수 있다.

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> listStream = list.stream();

Array

Stream의 of() 메소드 혹은 Arrays의 stream() 메소드를 사용한다.

Stream<String> stream = Stream.of("a", "b", "c");
Stream<String> stream = Stream.of(new String[] {"a", "b", "c"});
Stream<String> stream = Arrays.stream(new String[] {"a", "b", "c"});
Stream<String> stream = Arrays.stream(new String[] {"a", "b", "c"}, 0, 3);

2️⃣ Stream 가공

  • 0개 이상의 중간 연산들로 요소들을 가공할 수 있다.
  • 파라미터로는 함수형 인터페이스가 사용된다.
  • 중간 연산들의 연결을 위해 모든 연산의 반환값은 Stream이다.

filter

필터링, 말그대로 조건과 일치하는 데이터만을 정제한다.
람다식과의 궁합이 좋다.

List<String> myList = Arrays.asList("minsu", "minji", "youngsu");
Stream<String> stream = myList.stream().filter(name -> name.contains("m"));

map

말 그대로 기존의 Stream 요소 하나하나를 매핑하여 새로운 Stream을 형성한다.
map(c -> c.toUpperCase()) 대문자로 변경하는 코드
map(s -> s.length()) 문자열의 길이를 나타내는 코드

sorted

Stream의 요소들을 정렬한다.
sorted() 오름차순 정렬
sorted(Comparator.reverseOrder()) 내림차순 정렬

distinct

중복된 데이터가 존재하는 경우 중복을 제거한다.
distinct()는 Object의 equals() 메소드를 사용한다.

클래스를 Stream으로 사용한다면 equals와 hashCode를 오버라이드 해야만 distinct()가 적용된다.

@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		Employee employee = (Employee) o;
		return Objects.equals(name, employee.name);
}
@Override
	public int hashCode() {
		return Objects.hash(name);
}

peek

Stream의 결과에 영향을 미치지 않고 특정 연산을 수행한다.
중간에 출력하고 싶을 때 유용하게 쓰인다.

int sum = IntStream.of(1, 3, 5, 7, 9)
  .peek(System.out::println)
  .sum();

3️⃣ Stream 결과

  • 하나의 연산만 사용할 수 있다.

max/min/sum/average/count

  • max/min/average는 null의 경우 값을 특정할 수 없으므로 Optional의 형태로 반환된다.
  • sum/count는 0으로 특정할 수 있으므로 원시 값을 반환한다.

collect

요소들을 List나 Set, Map 등 다른 종류의 결과로 수집하고 싶은 경우 사용한다.
형태 : Object collect(Collector collector)

  • collect() : 스트림의 최종연산, 매개변수로 Collector를 필요로 한다.
  • Collector : 인터페이스, collect의 파라미터는 이 인터페이스를 구현해야한다.
  • Collectors : 클래스, static메소드로 미리 작성된 컬렉터를 제공한다.
List<Product> productList = Arrays.asList(
	new Product(23, "potatoes"),
	new Product(14, "orange"),
	new Product(13, "lemon"),
	new Product(23, "bread"),
	new Product(13, "sugar"));

Collectors.toList()

Stream에서 작업한 결과를 List로 반환받는다.

List<String> nameList = productList.stream()
    .map(Product::getName)
    .collect(Collectors.toList());

Collectors.joining()

Stream에서 작업한 결과를 하나의 String으로 이어붙인다.
파라미터는 (구분자, 접두사, 접미사)

String listToString = productList.stream()
  	.map(Product::getName)
  	.collect(Collectors.joining("-", "@", "#"));
// @potatoes-orange-lemon-bread-sugar#

그 외

Collectors.averagingInt(), Collectors.summingInt(), Collectors.summarizingInt(), Collectors.groupingBy(), Collectors.partitioningBy()

match

  • anyMatch: 1개의 요소라도 해당 조건을 만족하는가
  • allMatch: 모든 요소가 해당 조건을 만족하는가
  • nonMatch: 모든 요소가 해당 조건을 만족하지 않는가
    boolean으로 반환된다.

forEach

names.stream()
    .forEach(System.out::println);
profile
성장 중독 | 서버, 데이터, 정보 보안을 공부합니다.

0개의 댓글