전체 -> 맵핑 -> 필터링 1 -> 필터링 2 -> 결과 만들기 -> 결과물
Stream, Stream 과 같은 것들
자바 스트림 API는 숫자 스트림을 효율적으로 처리할 수 있도록 세 가지 기본형 특화 스트림을 제공한다.
IntStream, DoubleStream, LongStream
종류 | 데이터형 | 크기(byte / bit) |
---|---|---|
논리형 | boolean | 1 / 8 |
문자형 | char | 2 / 16 |
정수형 | byte | 1 / 8 |
정수형 | short | 2 / 16 |
정수형 | int | 4 / 32 |
정수형 | long | 8 / 64 |
실수형 | float | 4 / 32 |
실수형 | double | 8 / 64 |
이러한 특화 스트림은 숫자 스트림의 합계를 계산하는 sum, 최댓값 요소를 검색하는 max 같이 자주 사용하는 숫자 관련 리듀싱 연산 수행 메서드를 제공한다!
mapToInt
, mapToDouble
, mapToLong
메서드를 이용하면 일반 스트림을 특화 스트림으로 변환할 수 있다.
int totalPayPrice = pays.stream()
.mapToInt(Pay::getPayPrice)
.sum();
💡 저 ::
은 도대체 뭘까?
자바의 메소드 레퍼런스라는 것으로, 람다식을 다른 방식으로 표현한 것이다.
예
람다식 (text)-> System.out.println(text)
메소드 레퍼런스 System.out :: println
메소드 레퍼런스는 [ClassName] :: [MethodName]
형식으로 입력하고,
메소드를 호출하는 것이지만 괄호()는 써주지 않고 생략한다!
.mapToInt(Pay::getPayPrice)
람다식로 변환하면?
.mapToInt(onePay → onePay.getPayPrice)
List를 int[]로 변환하고 싶다면?
mapToInt
이용!
int[] arr = list.stream()
.mapToInt(i -> i) // == mapToInt(Integer::intValue)
.toArray();
boxed() 메서드는 IntStream 같이 원시 타입에 대한 스트림 지원을 클래스 타입(예: IntStream
-> Stream<Integer>
) 으로 전환해준다.
사용 예: int 자체로는 Collection에 못 담기 때문에 Integer 클래스로 변환하여 List<Integer>
로 담기 위해 사용한다.
List<Integer> list1 = Arrays.stream(arr) // == IntStream.of(arr)
.boxed()
.collect(Collectors.toList());
if문이라고 생각하면 편하다.
일치하는 모든 요소를 포함하는 스트림으로 반환한다.
메뉴 List에서 베지테리안 메뉴만 찾아서 리스트로 저장하고 싶다면?
List<Dish> vegetarianMenu = menu.stream()
.filter(Dish::isVegetarian) // 리턴값이 true면 다음 단계 진행, false면 버려짐!
.collect(Collectors.toList());
스트림의 요소들을 우리가 원하는 자료형으로 변환할 수 있다.
toList()
, toSet()
, toMap()
, toCollection()
stream.collect(Collectors.toSet()); //set으로 변환
stream.collect(Collectors.toList()); //list 변환
stream.collect(Collectors.joining()); //요소를 다 이어붙여서 하나의 string으로 변환
stream.collect(Collectors.joining(", ")); //요소들 사이에 ","을 넣어서 한개의 string 반환
List나 Set이 아닌 특정 컬렉션을 지정하려면 toCollection()
에 해당 컬렉션의 생성자 참조를 매개변수로 넣어주면 된다.
ArrayList<String> list = names.stream()
.collect(Collectors.toCollection(ArrayList::new));
stream.toArray()
사용!Person[] personArray1 = personStream1.toArray(Person[]::new);
스트림을 우리가 원하는 모양의 새로운 스트림으로 변환할 수 있다.
스트림 내 문자열을 모두 대문자로 변경한 스트림 만들기?
Stream<String> stream = names.stream()
.map(String::toUpperCase);
anyMatch
allMatch
noneMatch
List<String> names = Arrays.asList("Eric", "Elena", "Java");
boolean anyMatch = names.stream()
.anyMatch(name -> name.contains("a"));
boolean allMatch = names.stream()
.allMatch(name -> name.length() > 3);
boolean noneMatch = names.stream()
.noneMatch(name -> name.endsWith("s"));
결과는 모두 true!
1.int[] numbers = {1, 2, 3, 4, 5};
위와 같은 배열이 있을 때,
스트림을 활용해서 아래와 같은 동작을 수행하자!
1. 홀수만 골라서, → filter()
2. 2를 곱한 뒤, → map()
3. 배열에 저장한다. → toArray
int[] result = Arrays.stream(numbers)
.filter(num -> num % 2 == 1)
.map(num-> num * 2) -> 스트림
.toArray();
2.int[] data = {5, 6, 4, 2, 3, 1, 1, 2, 2, 4, 8};
위와 같은 배열이 있을 때,
스트림을 활용해서 아래와 같은 동작을 수행하자!
1. 짝수만 뽑은 뒤, → filter
2. 중복을 제거하고, →
3. 역순으로 정렬해서 →
4. 출력한다. → foreach
Arrays.stream(data)
.boxed() // IntStream에서 -> Stream<Integer>로 변환
.filter(n -> n % 2 == 0)
.distinct() // 중복 제거
.sorted(Comparator.reverseOrder())
.forEach(System.out :: println); // == .forEach((num) -> System.out.println(num))
boxed
하는 이유?sorted(Comparator.reverseOrder())
를 하기 위함.sorted()
는 내림차순이 불가능!!3.프로그래머스 음양 더하기
class Solution {
public int solution(int[] absolutes, boolean[] signs) {
int sum = 0;
for(int i=0; i<absolutes.length; i++) {
if(!signs[i]) {
absolutes[i] *= -1;
}
sum += absolutes[i];
}
return sum;
}
}
스트림 활용 리팩토링
import java.util.stream.IntStream;
class Solution {
public int solution(int[] absolutes, boolean[] signs) {
int sum = IntStream.range(0, absolutes.length)
.map(i -> !signs[i] ? -absolutes[i] : absolutes[i])
.sum();
return sum;
}
}