Stream에 대한 정의는 다음과 같습니다.
A sequence of elements supporting sequential and parallel aggregate operations.
출처 : https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
Stream은 선언형으로 Collection, Array, I/O 리소스등 저장된 데이터에 대해서 filtering,matching,mapping등과 같은 복잡한 데이터 처리 작업을 수행하는데 사용됩니다.
그러나 이쯤에서 드는 의문이 한가지 있습니다.
기존 collection 데이터 등을 잘 사용하고 있었는데 굳이 스트림이라는 새로운 것을 왜 만드는 것일까?
무슨 차이가 있는 것일까? 해당 내용을 구글링하다보니 나온 내용이 있습니다.
공통점
차이점
List<Integer> list = Arrays.asList(1,2,3,4);
//Iterator
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()){
int number = iter.next();
System.out.println("값 ::: " + number);
}
//Stream
Stream<Integer> stream = list.stream();
stream.forEach(number -> System.out.println("값 ::: " + number));
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//Stream
Stream<Integer> stream = list.stream();
stream.filter(i -> i %2 ==0)
.forEach(number -> System.out.println("값 ::: " + number));
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//Stream
Stream<Integer> stream = list.stream();
stream.filter(i -> i %2 ==0)
.map(i-> i*2)
.forEach(number -> System.out.println("값 ::: " + number));
int arr [][] = {{1, 2, 3}, {4, 5}, {6, 7, 8}, {9, 10}};
Stream.of(arr)
.flatMapToInt(IntStream::of)
.forEach(i-> System.out.println("값 ::: " + i));
List<Integer> list = Arrays.asList(1,2,3,4,5,1,2,3,4,5);
//Stream
Stream<Integer> stream = list.stream();
stream.sorted()
.forEach(number -> System.out.println("값 ::: " + number));
Stream과 같이 java8에서 등장한 개념이 Optional이다.
java 공식문서에 따르면 다음과 같이 정의 되어 있습니다.
A container object which may or may not contain a non-null value.
널이 아닌 값을 포함하거나 포함하지 않을 수있는 컨테이너 객체입니다.
해당 설명을 보아하니 null 관련 체크를 하는 기능을 하는거 같다.
근데 if-else를 이용해서 null을 체크 해도 될텐데 Optional을 사용할 필요가 있을까?
API Note:
Optional is primarily intended for use as a method return type where there is a clear need to represent “no result,” and where using null is likely to cause errors. A variable whose type is Optional should never itself be null; it should always point to an Optional instance.
-> Optional은 주로 "결과 없음"을 나타내야하는 명확한 필요성이 있고 null을 사용하면 오류가 발생할 가능성이있는 메서드 반환 유형으로 사용하기위한 것입니다. 유형이 Optional 인 변수는 자체적으로 null이 아니어야합니다. 항상 Optional 인스턴스를 가리켜야합니다
출처 : https://docs.oracle.com/javase/9/docs/api/java/util/Optional.html
예측하지 못하는 null로 부터 개발자들에게 분리를 시키기 위해서 새로 만들어 진거 같다.
Map<Integer,String> name = new HashMap<>();
name.put(1,"철수");
name.put(2,"영희");
name.put(3, "길동");
//Optional X
String searchName = name.get(4); // null 발생
if(searchName == null){
new Exception("값이 없습니다.");
}else{
System.out.println("이름 ::: " + searchName);
}
// Optional O
Optional<String> nameOptaionl = Optional.ofNullable(name.get(4));
nameOptaionl.orElseThrow(() -> new Exception("값이 없습니다."));
System.out.println("이름 ::: " + nameOptaionl.get());
Optional<Integer> optional = Optional.of(1);
System.out.println(optional.get());
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);
Optional<Integer> optional = Optional.ofNullable(list.get(9));
List<String> list = Arrays.asList("김범수","나얼","박효신","이수", null);
System.out.println("단어 ::: " + Optional.ofNullable(list.get(4)).orElse("없음"));
List<String> list = Arrays.asList("김범수","나얼","박효신","이수", null);
System.out.println("단어 ::: " + Optional.ofNullable(list.get(4)).orElseGet(() -> "데이터 없음"));
※ orElse vs orElseGet
orElse 나 orElseGet나 같은 것들이 리턴된다.
그럼 orElse 나 orElseGet이나 같은 기능을 하는 것이 아닌가?
정답은 "같지 않다".
즉 위의 orElseGet을 람다식을 없애면 이해하기 쉽다.
List<String> list = Arrays.asList("김범수","나얼","박효신","이수", null);
System.out.println("단어 ::: " + Optional.ofNullable(list.get(1)).orElseGet( new Supplier<String>() {
@Override
public String get() {
return "없음";
}
}));
참조 : java8 공식문서