티스토리 뷰
개념
Predicate<T>
를 파라미터로 받아서Predicate
가 true인 모든 요소를 포함하는 스트림을 반환하는 메서드
예제
-
아래 예제에서 사용되는 내용들은 다양한 상황을 연출하기 위해서 임의로 만들어진 내용이므로 특정 속성에 대해서 왜 저 타입이 사용되었는지 의문을 가지지 말자!
-
예제 코드에서 사용되고 있는 스펙
- Java 15 preview (record라는 새로운 클래스 개념을 사용하기 위해서 해당 프리뷰 버전을 사용. 하위 버전의 경우는 일반 클래스를 생성한 후 getter를 만들고 사용하면 됨) - 참고
- JUnit 5
- Gradle 6.7
기본 데이터 생성
public record Person(int no, String name, int age, Nation nation, int gender) {
}
public enum Nation {
KOREA, JAPAN, CHINA, USA, UK
}
private final FilterUsage filterUsage = new FilterUsage();
private final List<Person> people = List.of(
new Person(1, "hong", 15, Nation.CHINA, 1),
new Person(2, "kim", 20, Nation.KOREA, 0),
new Person(3, "miya", 18, Nation.JAPAN, 1),
new Person(4, "hong", 30, Nation.USA, 0));
특정 나이 이상의 사람들 조회
- 특정 나이 이상의 사람들을 필터링하는 메서드를 만들어보자.
public List<Person> getPeopleByAgeGreaterThanEqual(List<Person> people, int age) {
return people.stream()
.filter(p -> p.age() >= age)
.collect(Collectors.toList());
}
- 나이가 20세 이상인 사람을 조회해보자.
@Test
@DisplayName("특정 나이 이상의 사람들 조회")
void getPeopleByAgeGreaterThanEqualTest() {
final var result = filterUsage.getPeopleByAgeGreaterThanEqual(people, 20);
result.forEach(System.out::println);
assertEquals(2, result.size());
assertEquals("kim", result.get(0).name());
assertEquals("hong", result.get(1).name());
}
- 콘솔에 다음과 같은 실행 결과와 함께 테스트가 성공한다.
- 이번에는 위에서 만든
getPeopleByAgeGreaterThanEqual
메서드를 사용해서 결과로 빈 리스트가 반환되는 즉, 필터를 통과한 데이터가 없는 경우에 대해서 알아보자 - 나이가 40세 이상인 사람을 조회해보자.
@Test
@DisplayName("특정 나이 이상의 사람들 조회(필터 결과가 없음)")
void getPeopleByAgeGreaterThanEqualWithEmptyResultTest() {
final var result = filterUsage.getPeopleByAgeGreaterThanEqual(people, 40);
result.forEach(System.out::println);
assertEquals(Collections.emptyList(), result);
}
- 콘솔에 출력되는 결과는 없고 테스트는 성공한다.
특정 성별이 아닌 사람들 조회
- 특정 성별이 아닌 사람들을 필터링하는 메서드를 만들어보자.
public List<Person> getPeopleByGenderNot(List<Person> people, int gender) {
return people.stream()
.filter(Predicate.not(p -> p.gender() == gender))
.collect(Collectors.toList());
}
- 위의 코드에서
Predicate.not()
이라는 메서드가 사용되었는데, 다음의 시그니쳐를 가진 메서드이다.
Predicate
함수형 인터페이스의 static 메서드로Predicate
를 인자로 받아서 그 결과를 반전시키는 메서드이다.- 그 반환 결과는
Predicate
로filter
메서드에 파라미터로 사용할 수 있다. - 위 메서드 설명을 읽어보면 메서드 바로 위에 Since: 11 를 통해 Java 11에 추가되어 상위 버전에서 사용될 수 있음을 알 수 있다.
- Java 10 이하 버전을 사용하고 있다면
Predicate.not()
메서드를 사용할 수 없기 때문에 다음과 같이 작성하면 된다.
public List<Person> getPeopleByGenderNot(List<Person> people, int gender) {
return people.stream()
.filter(p -> p.gender() != gender)
.collect(Collectors.toList());
}
-
물론 Java 11 이상 버전을 사용하고 있어도
Predicate.not()
을 사용하지 않고 위의 코드처럼 사용해도 무방하다.- 필자의 경우 코드의 선언적으로 명시해주는 스타일을 좋아해서 위의
Predicate.not()
방식을 선호한다. - 두 방식의 의미적 차이를 추가적으로 공부하거나 고민해보면 좋을 것 같다.
- 필자의 경우 코드의 선언적으로 명시해주는 스타일을 좋아해서 위의
-
성별이 '남자'가 아닌 사람을 조회해보자. (여기서 gender가 0이면 남자이다.)
@Test
@DisplayName("특정 성별이 아닌 사람들 조회")
void getPeopleByGenderNotTest() {
// 0: Male, 1: Female
final var result = filterUsage.getPeopleByGenderNot(people, 0);
result.forEach(System.out::println);
assertEquals(2, result.size());
assertEquals("hong", result.get(0).name());
assertEquals("miya", result.get(1).name());
}
- 콘솔에 다음과 같은 실행 결과와 함께 테스트가 성공한다.
특정 나라에 살고 특정 나이 이상인 사람들 조회
- 특정 나라에 살고 있고 특정 나이 이상인 사람들을 필터링하는 메서드를 만들어보자.
public List<Person> getPeopleByNationAndAgeGreaterThanEqual(List<Person> people, Nation nation, int age) {
return people.stream()
.filter(p -> p.nation() == nation)
.filter(p -> p.age() >= age)
.collect(Collectors.toList());
}
- 다음과 같이 필터 조건이 여러 개일 경우
filter
메서드를 연결해서 사용할 수 있다. - 다음과 같이 하나의 필터로 사용할 수도 있다.
public List<Person> getPeopleByNationAndAgeGreaterThanEqual(List<Person> people, Nation nation, int age) {
return people.stream()
.filter(p -> p.nation() == nation && p.age() >= age)
.collect(Collectors.toList());
}
-
실행 결과는 동일하게 나타난다.
-
위 두가지 방식에 대해서도 고민해보면 좋을 것 같다.
- 필자는 필터에서 사용하는 필드가 다르다면 처음 방식처럼 분리하는 것이 좋다고 생각한다. 직관적이기 때문이다.
- 성능적인 문제가 있는지 확인해보지는 않았지만 아시는 분이나 심심해서 성능 측정을 해보신 분이 계시다면 공유해주시면 감사합니다ㅎㅎ
-
한국에 살고있고 나이가 15세 이상인 사람을 조회해보자.
@Test
@DisplayName("특정 나라에 살고 특정 나이 이상인 사람들 조회")
void getPeopleByNationAndAgeGreaterThanEqualTest() {
final var result = filterUsage.getPeopleByNationAndAgeGreaterThanEqual(people, Nation.KOREA, 15);
result.forEach(System.out::println);
assertEquals(1, result.size());
assertEquals("kim", result.get(0).name());
}
- 콘솔에 다음과 같은 실행 결과와 함께 테스트가 성공한다.
이상 Stream API에서 사용하는 중간 연산 중 많이 사용되는 filter
메서드의 간단한 사용법에 대해 살펴보았다.
'프로그래밍 > Java' 카테고리의 다른 글
[Stream API] 중간 연산 - slicing 관련 메서드들 (0) | 2021.01.03 |
---|---|
[Stream API] 중간 연산 - distinct 메서드 (0) | 2020.12.31 |
Intellij IDEA에서 Gradle을 사용해 Java Preview 버전의 코드 테스트하기. (0) | 2020.10.28 |
[Java 14] Helpful NullPointerExceptions (0) | 2020.08.12 |
[Java 14] Enhanced Switch Expressions (2) | 2020.08.04 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- IntelliJ
- 람다
- 토이 프로젝트
- 중간 연산
- 스트림
- jdk14
- Stream API
- 변경사항
- modern java
- 자바
- 충북 콕! 콕!
- 계획
- Java8
- java
- mapToObj
- flaMap
- 익명 클래스
- import문
- 개발자
- 회고
- #예제 #example #가계부 #Account Book
- 다짐
- #React #ReactJS #리액트
- flatMapToLong
- flatMapToDouble
- #배열 #array #map 함수
- 목표
- lambda
- flatMapToInt
- java14
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함