자료의 대상과 관계없이 동일한 연산을 수행하며 일관성 있는 연산으로 자료의 처리를 쉽고 간단하게 해주는 것이다.
배열, 컬렉션을 대상으로 연산을 수행ㅇ하며 자료 처리에 대한 추상화가 구현되었다.
한번 생성하고 사용한 스트림은 재사용 할 수 없다!! 스트림을 생성하여 연산을 수행하면 해당 스트림은 소모되고 다른 연산을 수행하기 위해서는 새로운 스트림을 다시 생성해야한다.
자료에 대한 스트림을 생성하면 스트림이 사용하는 메모리 공간도 별도로 생성되므로 연산이 수행되어도 기존 자료에 대한 변경은 발생하지 않는다.
스트림의 연산은 중간 연산과 최종 연산으로 구분되며 스트림의 중간 연산은 여러개의 연산이 적용될 수 있지만 최종 연산은 마지막에 한번만 적용된다.
중간연산은 최종 연산이 호출되어야 중간 연산에 대한 수행이 이루지고 그 결과가 만들어져 중간 연산에 대한 결과는 연산중에 알 수 없다.
중간연산은 지연 연산이라고 불리기도 한다.
최종 연산이 호출될 때 중간 연산이 수행된다.
filter(), map(), sorted() 등이 존재한다.
filter() : 조건에 맞는 요소를 추출하는 연산
map() : 요소를 변환해주는 연산
스트림이 관리하는 자료를 하나씩 소모해가며 연산이 수행된다.
forEach(), count(), sum()등이 존재한다.
forEach() : 요소를 하나씩 꺼내주는 연산
count() : 요소의 개수를 반환
sum() : 요소들의 합을 반환
import java.util.Arrays;
import java.util.stream.IntStream;
public class InArrayStreamTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {1,2,3,4,5};
for (int num: arr) {
System.out.println(num);
}
System.out.println();
Arrays.stream(arr).forEach(n-> System.out.println(n));
// Stream과 람다식을 사용하여 위의 코드와 같은 결과를 낼 수 있다.
IntStream is = Arrays.stream(arr);
// IntStream 인스턴스를 생성하여 is.~ 을 통해 연산자들을 사용할 수도 있다.
is.forEach(n-> System.out.println(n));
// Stream은 한번 사용하면 더이상 사용을 못하고 새로 만들어줘야한다.
// is Stream은 위에서 사용을 했기에 다시 사용하려고 하면 오류가 발생한다.
// is.forEach(n-> System.out.println(n));
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class ArrayListStreamTest {
public static void main(String[] args) {
List<String> sList = new ArrayList<>();
sList.add("Tomas");
sList.add("Edward");
sList.add("Jack");
Stream<String> stream = sList.stream();
stream.forEach(s-> System.out.println(s));
System.out.println();
//14,15라인의 Stream은 한번 사용하여 재사용 불가, 아래에서는 새로 생성
sList.stream().sorted().forEach(s-> System.out.print(s + "\t"));
System.out.println("\n");
sList.stream().map(s->s.length()).forEach(n-> System.out.print(n + "\t"));
// map은 요소를 변환하기 위해 사용
System.out.println("\n");
sList.stream().filter(s->s.length() >= 5).forEach(n-> System.out.print(n + "\t"));
// filter는 조건문과 같은 것
}
}
T reduce(T identify, BinaryOperator<T> accumulator)
T reduce(BinaryOperator<T> accumulator) // binaryOperator만 사용할 수도 있다.
위의 코드에서 첫번째 parameter는 초기 값이며 두번째 parameter는 람다식을 직접 구현하거나 람다식이 긴 경우에는 BinaryOperator라는 인터페이스를 구현한 클래스를 쓸 수도 있다.
배열의 모든 합을 구하는 reduce연산의 예제
첫번째 parameter인 0은 값의 초기값이고 합을 구하는 연산을 통해 초기값인 0에 배열에 있는 모든 값들을 더하게 된다.
Arrays.stream(arr).reduce(0, (a,b)->a+b));
BinaryOperator는 람다식이 긴 경우 사용을 한다.
BinaryOperator를 사용하면 apply라는 metod를 반드시 재정의 하여야한다.
import java.util.Arrays;
import java.util.function.BinaryOperator;
class CompareString implements BinaryOperator<String>{
@Override
public String apply(String s1, String s2) {
// TODO Auto-generated method stub
if (s1.getBytes().length >= s2.getBytes().length) return s1;
else return s2;
}
}
public class ReduceTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] greetings = {"안녕하세요~~~", "hello", "Good morning", "반갑습니다^^"};
// reduce function에서 람다식을 사용한 예시
System.out.println(Arrays.stream(greetings).reduce("",(s1, s2) ->
{if (s1.getBytes().length >= s2.getBytes().length) return s1;
else return s2; }
));
// BinaryOperator를 사용한 예시
String str = Arrays.stream(greetings).reduce(new CompareString()).get();
System.out.println(str);
}
}