https://mangkyu.tistory.com/114
https://futurecreator.github.io/2018/08/26/java-8-streams/
문제 : https://mangkyu.tistory.com/116
: .filter( -> ());
stream에서 조건에 맞는 데이터만을 정제하여 더 작은 컬렉션을 만들어내는 연산이다.
java에서는 filter 함수의 인자로 함수형 인터페이스 predicate를 받고 있기 때문에 boolean을 반환하는 람다식을 작성하여 filter함수를 구현할 수 있다.
예를 들어 String에 a가 들어간 문자열만을 포함하도록 필터링
Stream<String> stream =
list.stream()
.filter(name -> name.contains("a"));
Stream<String> stream =
names.stream()
.map(s -> s.toUpperCase());
map함수의 람다식은 메소드 참조를 이용해 변경이 가능하다
이번에는 메소드 참조를 이용하여 파일은 stream을 파일이름의 stream으로 변경해보자
Stream<File> fileStream = Stream.of(new File("Test1.java"), new File("Test2.java"), new File("Test3.java"));
//Stream<File> --> Stream<String> 변환
Stream<String> fileNameStream = fileStream.map(File::getName);
: 요소 정렬
Stream<String> stream = list.stream()
.sorted()
Stream<String> stream = list.stream()
.sorted(Comparator.reverseOrder())
: 중복된 데이터가 존재하는 경우 중복을 제거하기 위해서 사용한다
distinct는 중복된 데이터를 검사하기 위해서 Object의 equals() 메소드를 사용한다
예를 들어 중복된 stream의 요소들을 제거하기 위해서는 아래와 같이 사용
List<String> list = Arrays.asList("Java", "Scala", "Groovy", "Python", "Go", "Swift", "Java");
Stream<String> stream = list.stream()
.distinct()
// [Java, Scala, Groovy, Python, Go, Swift]
: 각각의 요소들에 대해 특정 작업을 수행할 뿐 결과에 영향을 주지 않는다
또한 peek 함수는 파라미터로 함수형 인터페이스 Consumer를 인자로 받는다
예를 들어 Stream 중간에 출력하기를 원할 때 사용
int sum = IntStream.of(1, 3, 5, 7, 9)
.peek(System.out::println)
.sum();
: 작업한 결과를 List로 반환
예제는 product의 이름을 변환하여 그 결과를 리스트로 반환
List<String> nameList = productList.stream()
.map(Product::getName)
.collect(Collectors.toList());
해당 결과를 set으로 반환받기를 원한다면 Collectors.toSet()을 사용하면 된다.
: stream에서 작업한 결과를 이어붙이기 하는 경우
delimiter : 각 요소 중간에 들어가 요소를 구분시켜주는 구분자
prefix : 결과 맨 앞에 붙는 문자
suffix : 결과 맨 뒤에 붙는 문자
String listToString = productList.stream()
.map(Product::getName)
.collect(Collectors.joining());
// potatoesorangelemonbreadsugar
String listToString = productList.stream()
.map(Product::getName)
.collect(Collectors.joining(" "));
// potatoes orange lemon bread sugar
String listToString = productList.stream()
.map(Product::getName)
.collect(Collectors.joining(", ", "<", ">"));
// <potatoes, orange, lemon, bread, sugar>
Stream의 요소들이 특정한 조건을 충족하는지 검사하고 싶은 경우에는 match 함수를 이용할 수 있다. match 함수는 함수형 인터페이스 Predicate를 받아서 해당 조건을 만족하는지 검사를 하게 되고, 검사 결과를 boolean으로 반환한다. match 함수에는 크게 다음의 3가지가 있다.
anyMatch: 1개의 요소라도 해당 조건을 만족하는가
allMatch: 모든 요소가 해당 조건을 만족하는가
nonMatch: 모든 요소가 해당 조건을 만족하지 않는가
예를 들어 다음과 같은 예시 코드가 있다고 할 때, 아래의 경우 모두 true를 반환하게 된다.
List<String> names = Arrays.asList("Eric", "Elena", "Java");
boolean anyMatch = names.stream()
.anyMatch(name -> name.contains("a"));
boolean allMatch = names.stream()
.allMatch(name -> name.length() > 3);
boolean noneMatch = names.stream()
.noneMatch(name -> name.endsWith("s"));
https://mangkyu.tistory.com/113
: 람다식으로 선언된 함수는 일급 객체이기 때문에 stream API의 매개변수로 전달이 가능해진다
// 기존의 방식
반환티입 메소드명 (매개변수, ...) {
실행문
}
// 예시
public String hello() {
return "Hello World!";
}
// 람다 방식
(매개변수, ... ) -> { 실행문 ... }
// 예시
() -> "Hello World!";
메소드 참조란 함수형 인터페이스를 람다식이 아닌 일반 메소드를 참조시켜 선언하는 방법이다. 일반 메소드를 참조하기 위해서는 다음의 3가지 조건을 만족해야 한다.
함수형 인터페이스의 매개변수 타입 = 메소드의 매개변수 타입
함수형 인터페이스의 매개변수 개수 = 메소드의 매개변수 개수
함수형 인터페이스의 반환형 = 메소드의 반환형
// 기존의 람다식
Function<String, Integer> function = (str) -> str.length();
function.apply("Hello World");
// 메소드 참조로 변경
Function<String, Integer> function = String::length;
function.apply("Hello World");
상황에 맞는 방법을 선택하여 사용할 것
: java NPE 예방
null값에 대해 고려해야하는 경우가 많은데 null값을 제대로 처리하지 안으면 NPE가 터진다.
안정적인 실행을 위해 NPE가 발생하지 않도록 중간중간 null 체크를 해줘야하는데
이게 코드를 더럽힌다 (null 체크를 해주는 코드를 작성해야한다)
: null일 수 있는 어떤 변수를 감싸주는 래퍼(wrapper)클래스 이다. optional 클래스는 제네릭으로 값의 타입을 지정해줘야한다
optional<T>
optional 클래스는 여러가지 메소드를 통해 value값에 접근하기 때문에 바로 NPE가 발생하지 않으며 null일수도 있는 값을 다루기 위한 다양한 메소드들을 제공한다