데이터 소스가 무엇(컬렉션프레임워크, 배열...)이든간에 같은 방식으로 다룰 수 있게 데이터를 추상화 하고 데이터를 다루는데 자주 사용되는 메서드들을 정의해 놓은 것
연산 결과가 스트림
인 연산, 스트림에 연속해서 중간 연산할 수 있다.
연산 결과가 스트림이 아닌 연산
. 스트림의 요소를 소모하므로 단 한번만 가능
요소의 타입이 T인 스트림은 기본적으로 Stream인데, 기본 자료형을 다루려면 오토박싱&언박싱이 발생하여 비효율성이 증가한다(예 - Integer <-> int) 비효율성을 줄이기 위해 데이터 소스의 요소를 기본형으로 다루는 스트림이 제공된다. (int[] -> IntStream, long[] -> LongStream, double[] -> DoubleStream)
람다식을 매개변수로 받아서 람다식에 의해 계산되는 값들을 요소로 하는 무한 스트림을 생성
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
static<T> Stream<T> generate(Supplier<T> s)
Stream<Integer> iterate = Stream.iterate(2, x -> x * 2); // 이전 값을 이용하여 다음 요소 계산, 무한스트림
Stream<Integer> generate = Stream.generate(() -> 1); // 이전요소 없이 다음 요소 계산
int[] array = IntStream.iterate(10, x -> x + 2).limit(5).toArray();
System.out.println(Arrays.toString(array)); // [10, 12, 14, 16, 18]
int[] array1 = IntStream.generate(() -> 1).limit(10).toArray();
System.out.println(Arrays.toString(array1)); // [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
String[] str = {"123", "456"};
String[] str1 = {"AB", "DET"};
Stream<String> str2 = Stream.of(str);
Stream<String> str3 = Stream.of(str1);
Stream<String> concat = Stream.concat(str2, str3);
Stream<T> skip(long n) // n만큼 건너뛰기
Stream<T> limit(long maxSize) // maxSize 만큼 자르기
IntStream intStream1 = IntStream.rangeClosed(1, 10);
intStream1.skip(4).limit(2).forEach(System.out::println); // skip -> 건너뛰기, limit -> 개수 제한
Stream<T> filter(Predicate<? super T> predicate)
Stream<T> distinct()
IntStream intStream5 = IntStream.of(1, 2, 2, 3, 3, 4, 5, 5, 6);
intStream5.distinct().forEach(System.out::println);
IntStream intStream6 = IntStream.range(1, 10);
intStream6.filter(x->x>5).forEach(System.out::println);
스트림의 요소에서 저장된 값 중에서 원하는 필드만 뽑아내거나 특정 형태로 변환해야 하는 경우
Stream<R> map(Function<? super T, ? extends R> mapper)
public class StreamMain1 {
public static void main(String[] args) {
List<Member> members = new ArrayList<>();
members.add(new Member("홍길동", 20));
members.add(new Member("유관순", 40));
members.add(new Member("이순신", 60));
List<Integer> collect = members.stream().map(x -> x.getAge()).collect(Collectors.toList());
collect.stream().forEach(System.out::println);
}
static class Member{
private String name;
private int age;
public Member(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
20
40
60
Comparator를 지정하지 않으면 스트림 요소의 기본 정렬 기준(Comparable)으로 정렬한다. 단, 스트림의 요소가 Comparable을 구현한 클래스가 아니면 예외가 발생한다.
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
기본 자료형 -> Stream<Integer>
로 변환해준다.
IntStream
->boxed()
->Stream<Integer>
LongStream
->boxed()
->Stream<Long>
DoubleStream
->boxed()
->Stream<Double>
Stream<Integer> boxed()
// Returns a Stream consisting of the elements of this stream, each boxed to an Integer.
public class StreamEx9 {
public static void main(String[] args) {
int[] nums = {11, 5, 3, 22, 15, 75};
// IntStream -> .boxex() -> Stream<Integer>
int[] array = Arrays.stream(nums).boxed().sorted(Comparator.reverseOrder()).mapToInt(x -> x).toArray();
System.out.println(Arrays.toString(array));
}
}
[75, 22, 15, 11, 5, 3]
forEach와 비슷하나 스트림의 요소를 소모하지 않는 중간 연산으로 연산 사이에 여러번 넣어도 된다.
map()은 연산결과로 Stream 타입의 스트림을 반환하지만 기본자료형인 int, long, double으로 반환해 주는 기본 스트림을 반환
일반 -> 기본자료형 :
mapToInt
,mapToLong
,mapToDouble
List<Integer>
->Stream<Integer>
->mapToInt(...)
->IntStream
// 정수 관련 특수 기능을 사용하기 위해서(연산의 효율성을 위해서)Set<Long>
->Stream<Long>
->mapToLong(...)
->LongStream
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)
IntStream mapToInt(ToIntFunction<? super T> mapper)
LongStream mapToLong(ToLongFunction<? super T> mapper)
스트림의 타입이 Stream<T[]>인 경우 Stream로 변환해 준다.
Stream<String> strStrm = Stream.of("abc", "def", "jklmn");
Stream<String> strStrm2 = Stream.of("ABC", "GHI", "JKLMN");
Stream<Stream<String>> strmStrm = Stream.of(strStrm, strStrm2);
Stream<String> strStream = strmStrm.map(s -> s.toArray(String[]::new)) // Stream<Stream<String>> -> Stream<String[]>
.flatMap(Arrays::stream); // Stream<String[]> -> Stream<String>
forEach()는 peek()와 달리 스트림의 요소를 소모하는 최종연산으로 반환 타입이 void이므로 스트림의 요소를 출력하는 용도로 사용된다.
void forEach(Consumer<? super T> action)
allMatch()
: 지정된 조건에 모든 요소가 일치하는지anyMatch()
: 지정된 조건에 일부 요소가 일치하는지noneMatch()
: 지정된 조건에 어떤 요소도 일치하지 않는지findFirst()
: 지정된 조건에 일치하는 첫 번째 것을 반환findAny()
: 지정된 조건에 일치하는 첫 번째 것을 반환(병렬 스트림에서 사용)boolean allMatch(Predicate<? super T> predicate)
boolean anyMatch(Predicate<? super T> predicate)
boolean noneMatch(Predicate<? super T> predicate)
스트림의 최종연산, 매개변수로 컬렉터를 필요로 한다.
Object collect(Collector collector) // Collector를 구현한 클래스의 객체를 매개변수로
List<String> names = stuStream.map(Student::getName).collect(Collectors.toList());
ArrayList<String> list = names.stream().collect(Collectors.toCollection(ArrayList::new));
Student[] stuNames = studentStream.toArray(Student[]::new); // OK
Object[] stuNames = studentStream.toArray(); // OK
String studentNames = stuStream.map(Student::getName).collect(Collectors.joining());
String studentNames = stuStream.map(Student::getName).collect(Collectors.joining(","));
String studentNames = stuStream.map(Student::getName).collect(Collectors.joining(",","[", "]"));
변환