컬렉션이나 배열에 데이터를 담고 원하는 결과를 얻기 위해 for문 또는 Iterator를 이용하여 코드를 작성하면 코드가 길고 알아보기 어려우며 재사용성이 떨어진다. 또한 데이터 소스마다 다른 방식으로 다뤄야한다. Collection 이나 Iterator와 같은 인터페이스를 이용해서 컬렉션을 다루는 방식을 표준화하긴 했지만 각 컬렉션 클래스에는 같은 기능의 메서드들이 중복해서 정의 되어 있다. 예를 들어 List를 정렬할 때는 Collections.sort(), 배열을 정렬할 때는 Arrays.sort()를 사용해야 한다.
String [] strArr = {"aaa", "bbb", "ccc"};
List<String> strList = Arrays.asList(strArr);
// 스트림으로 변경
Stream<String> strStream1 = strList.stream();
Stream<String> strStream2 = Arrays.stream(strArr);
// 화면에 출력하기
strStream1.sorted().forEach(System.out::println);
strStream2.sorted().forEach(System.out::println);
// 스트림을 쓰지 않았을 때
Arrays.sort(strArr);
Collections.sort(strList);
for (String str : strArr)
System.out.println(str);
for (String str : strList)
System.out.println(str);
List<String> sortedList = strStream2.sorted().collect(Collectors.toList());
strStream1.sorted().forEach(System.out::println);
int num = strStream1.count(); // 에러! 스트림은 이미 닫혔음
// System.out::println = (str) -> System.out.println(str)
strStream.sorted().forEach(System.out::println);
중간 연산 연산 결과가 스트림인 연산. 스트림에 연속해서 중간 연산할 수 있음
최종 연산 연산 결과가 스트림이 아닌 연산. 스트림의 요소를 소모하므로 단 한 번만 가능
중간 연산 목록
최종 연산 목록
int sum = strStream.parallel()
.mapToInt(s -> s.length())
.sum();
병렬 처리가 항상 더 빠른 결과를 얻게 해주는 것은 아니다.
Stream<T> Collection.stream()
List 스트림을 생성하기
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = lilst.stream();
intStream.forEach(System.out::println);
Stream<T> Stream.of(T.. values)
Stream<T> Stream.of(T[])
Stream<T> strStream = Arrays.stream(T[])
Stream<T> strStream = Arrays.stream(T[] array, int startInclusive, int enExclusive)
문자열 스트림 생성
Stream<String> strStream = Stream.of("a","b","c");
Stream<String> strStream = Stream.of(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"}, 0, 3);
int, long, double과 같은 기본형 배열을 소스로 하는 스트림 생성하는 메서드도 있다.
IntStream<T> IntStream.of(int.. values)
IntStream<T> IntStream.of(int[])
IntStream Arrays.stream(int[])
IntStream Arrays.stream(int[] array, int startInclusive, int enExclusive)
IntStream.range(int begin, int end) // end 미포함
IntStream.rangeClosed(int begin, int end) // end 포함
IntStream intStream = new Random().ints(); // 무한 스트림
intStream.limit(5).forEach(System.out::println); // 5개 출력
IntStream intStream = new Randowm().ints(5); // 크키가 5인 난수 스트림
static <T> Stream<T> iterate(T seed, UnaryOperateor<T> f)
static <T> Stream<T> generate(Supplier<T> s) // 매개변수 없어야함
iterate() 예시
// 무한 스트림
Stream<Integer> evenStream = Stream.iterate(0, n->n+2);
// 0, 2, 4, 6, ...
generate() 예시
// 무한 스트림
Stream<Integer> oneStream = Stream.generate(() -> 1);
Stream<Integer> evenStream = Stream.iterate(0, n->n+2).mapToInt(Integer::calueOf);
Stream<Integer> stream = evenStream.boxed();
String[] str1 = {"123", "456", "789"};
String[] str2 = {"ABC", "abc", "DEF"};
Stream<String> strs1 = Stream.of(str1);
Stream<String> strs2 = Stream.of(str2);
Stream<String> strs3 = Stream.concat(strs1, strs2); // 하나로 연결
IntStream intStream = IntStream.rangeClosed(1, 10); // 1~10
intStream.skip(3).limit(5).forEach(System.out::print); //45678
IntStream intStream = IntStream.of(1, 2, 2, 2, 3, 3, 4, 5, 5, 6);
intStream.distinct().forEach(System.out::print); // 123456
IntStream intStream = IntStream.rangeClosed(1, 10); // 1~10
intStream.filter(i -> i%2 == 0 || i%3 == 0).forEach(System.out::print);
Stream<String> strStream = Stream.of("dd", "aaa", "CC", "cc", "b);
strStream.sorted().forEach(System.out::print); // CCaaabccdd
예를 들어 studentStream을 반별, 성적순, 이름순으로 정렬하면 아래와 같다.
studentStream.sorted(Comparator.comparing(Student::getBan)
.thenComparing(Student::getTotalScore)
.thenComparing(Student::getName)
.forEach(System.out.::println);
Stream<File> fileSteam = Stream.of(new File("Ex1.java"), new File("Ex1"), new File("Ex1.bak"));
Stream<STring> filenameStream = fileStream.map(File::getName);
filenameStream.forEach(System.out::println);
fileStream.map(File::getName)
.filter(s -> s.indexOf('.') != -1)
.map(s -> s.substring(s.indexOf('.')+1))
.map(String::toUpperCase)
.distinct()
.forEach(System.out::print); // JAVABAK
fileStream.map(File::getName)
.filter(s -> s.indexOf('.') != -1)
.peek(s->System.out.printf("filename=%s%n" s)) // 파일명
.map(s -> s.substring(s.indexOf('.')+1))
.peek(s->System.out.printf("extension=%s%n", s)) // 확장자
.map(String::toUpperCase)
.distinct()
.forEach(System.out::print); // JAVABAK
예시) 모든 학생의 성적을 합산한다면
Stream<Integer> studentScoreStream = studentStream.map(Student::getTotalScore);
// mapToInt()를 사용하면 Integer를 int로 변환할 필요가 없기 때문에 더 효율적이다.
Stream<Integer> studentScoreStream = studentStream.mapToInt(Student::getTotalScore);
int allTotalScore = studentScoreStream.sum();
int sum()
OpionalDouble average()
OptionalInt max()
OptionInt min()
이 메서드들은 최종 연산이기 때문에 호출 후 스트림이 닫힌다. 그래서 summaryStatistics() 라는 메서드를 제공한다.
IntSummaryStatistics stat = scoreStream.summaryStatistics();
long totalCount = stat.getCount();
long totalScore = stat.getSum();
double avgScore = stat.getAverage();
int minScore = stat.getMin();
int maxScore = stat.getMax();