스트림(Stream)
List나 Array의 데이터를 처리하기 위해 for문이나 Iterator를 사용하여 처리하였는데 이러한 문법은 재사용성이 떨어진다. 또한 List와 Array의 중복되는 메소드로 인해 코드의 길이가 길어지게 되는데 스트림을 사용하면 해결이 가능하다.
예를 들어 List와 Array를 이용하여 정렬하는 코드를 보자면 같은 로직으로 처리하는데 코드가 중복된다.
Arrays.sort(strArr); // 배열 정렬
Collections.sort(strList); // 리스트 정렬
for(String str: strArr)
System.out.println(str);
for(String str: strList)
System.out.println(str);
위와 같은 로직을 스트림으로 구현하면 훨씬 깔끔하게 되는 것을 확인할 수 있다.
Stream<String> stream1 = strList.stream(); // 리스트의 스트림
Stream<String> stream2 = Arrays.stream(strArr); // 배열의 스트림
stream1.sorted().forEach(System.out::println);
stream2.sroted().forEach(System.out::println);
스트림의 특징
- 스트림을 사용하면서 주의해야 할 점은 스트림은 원본 데이터 소스를 읽기만 할 뿐 변경하지 않는다. 스트림의 결과를 사용하려면 새로운 변수에 담아야 한다.
List<String> sortedList = stream2.sorted().collect(Collectors.toList());
- 스트림은 일회용이다. 스트림도 Iterator처럼 데이터를 한번 읽고다면 다시 사용할 수 없다. 필요하다면 스트림을 다시 생성해야한다.
stream1.sorted().forEach(System.out::println);
int numOfStr = stream.count(); // 에러 발생
- 스림은 작업을 내부 반복으로 처리한다. 코드가 깔끔하게 보이는 이유 중 하나이다.
스트림의 연산
스트림 자르기 - skip(), limit()
List<String> strList = new ArrayList<String>(); // aa, bb, cc, dd, ee, ff // 앞에서부터 n개의 요소를 자름 strList.stream().limit(3).forEach(e-> System.out.println); // aa, bb, cc // 앞에서 n개의 요소를 건너뜀 strList.stream().skip(3).forEach(e-> System.out.println); // dd, ee, ff
스트림의 요소 걸러내기 - filter(), distinct()
filter()는 주어진 조건(Predicate)에 맞지 않는 요소를 걸러내고 distinct()는 중복된 요소를 걸러낸다
List<String> strList = new ArrayList<String>(); // aa, aa, bb, cc, dd, ee, ff
//조건에 맞지 않는 요소 제거
strList.stream().filter(e-> e.equals("aa")).forEach(e-> System.out.println(e)); // aa
//중복된 요소 제거
strList.stream().distinct().forEach(e-> System.out.println); // aa, bb, cc, dd, ee, ff
- 정렬 - sorted()
- Comparator로 스트림을 정렬하는데 int값을 반환하는 람다식을 사용하는 것도 가능. 객체를 정렬하는 경우 Comparable을 구현해야함
// Person 클래스는 이름과 나이를 인자로 받음.
List<Person> personList = new ArrayList<Person>(); // person1(홍길동, 10), person2(아무개, 30), person3(미카엘, 20)
// ClassCastException 발생. Comparable 인터페이스 구현이 필요함
personList.stream().sorted().forEach(e -> System.out.println(e.getName());
// Person 클래스에 나이 비교하는 Comparable 구현..
personList.stream().sorted().forEach(e -> System.out.println(e.getName()); // 홍길동, 미카엘, 아무개