JAVA 8 부터 도입된 stream. 내가 사용했을 때 느꼈던 가장 큰 장점은 데이터가 어떻게 흘러가는지가 문장읽듯이 읽혀서 코드 가독성이 좋다는 점이다. 처음에는 사용법을 잘 몰라 어려웠지만 하나씩 하나씩 작성해보니 꽤나 익숙해졌고 코드 짤 때도 stream의 비중이 높아지고 있다. 다음은 내가 작성했던 stream 관련 코드 예제이다.
배열 출력하기
/* 배열 출력 */
String[] alphabetArr = new String[]{"A", "B", "C"};
Arrays.stream(alphabetArr).forEach(alphabet -> log.info(alphabet));
stream 함수 안에서 여러 문장 실행하기
List<Person> personList = new ArrayList<>();
/* 멀티 라인 */
personList.stream().forEach(person -> {
person.setName("아무개");
person.setAge(13);
});
forEach() 등 stream 메소드 안에서 여러 라인을 실행하고 싶을 때 {}
로 묶을 수 있다.
anyMatch, allMatch, noneMatch
/* personList 중 한 요소라도 조건을 만족하면 true 반환 */
boolean anyMatch = personList.stream()
.anyMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
/* personList 중 모든 요소가 조건을 만족하면 true 반환 */
boolean allMatch = personList.stream()
.allMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
/* personList 중 모든 요소가 조건을 만족하지 않으면 true 반환 */
boolean noneMatch = personList.stream()
.noneMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
anyMatch
한 요소라도 조건을 만족하면 true
allMatch
모든 요소가 조건을 만족하면 true
noneMatch
모든 요소가 조건을 만족하지 않으면 true
filter, findFirst
/* personList에서 filet 조건을 첫 번째로 만족하는 요소 반환 */
Person firstPerson = personList.stream()
.filter(person -> "아무개".equals(person.getName()))
.findFirst()
.get();
filter
해당 조건 만족하는 요소만 다음 stream 으로 넘긴다.
findFirst
첫 번째로 조건 만족하는 요소 찾기
collect
/* personList에서 age만 모아 List 로 반환 */
List<Integer> ageList = personList.stream()
.map(person -> person.getAge())
.collect(Collectors.toList());
/* personList에서 age만 모아 Set 으로 반환 */
Set<Integer> ageSet = personList.stream()
.map(person -> person.getAge())
.collect(Collectors.toSet());
.map(person -> person.getAge())
age 값들을 다음 stream으로 넘긴다.
.collect(Collectors.toList())
받은 age 값들은 List로 반환
.collect(Collectors.toSet())
받은 age 값들은 Set으로 반환
Map 다루기
/* personList에서 key가 name이고 value가 age인 Map 만들기 */
Map<String, Integer> personMap = personList.stream()
.collect(Collectors.toMap(Person::getName, Person::getAge));
/* personMap에서 value가 13인 요소의 key 리스트 반환 */
List<String> age13NameList = personMap.entrySet().stream()
.filter(person -> person.getValue() == 13)
.map(person -> person.getKey())
.collect(Collectors.toList());
/* personMap에서 value가 13인 요소의 key를 "," 로 이어붙이기 */
String names = personMap.entrySet().stream()
.filter(person -> person.getValue() == 13)
.map(Map.Entry::getKey)
.collect(Collectors.joining(","));
.collect(Collectors.toMap(Person::getName, Person::getAge))
받은 Person의 name, age 값들을 Map으로 반환
.collect(Collectors.joining(","))
넘어온 값들을 "," 로 join한 string 반환
mapToInt, mapToDouble, mapToObj + max, average + IntStream
/* personMap의 key인 name의 최대 글자 수 구하기 */
int nameMaxLength = personMap.keySet().stream()
.mapToInt(name -> name.length())
.max()
.getAsInt();
/* 나이 평균 구하기 */
double ageAvg = ageList.stream()
.filter(Objects::nonNull)
.mapToDouble(age -> age)
.average()
.getAsDouble();
/* personList에서 짝수 인덱스 요소만 리스트로 반환 */
List<Person> subPersonList = IntStream.range(0, personList.size())
.filter(i -> i % 2 == 0)
.mapToObj(personList::get)
.collect(Collectors.toList());
.mapToInt(name -> name.length())
name.length()를 int형으로 변환해 다음 stream으로 전달
.max()
넘어온 값들 중 최댓값 구하기
.mapToDouble(age -> age)
age 값을 double로 변환해 next stream으로 전달
.average()
넘어온 값들의 평균 구하기
IntStream.range(0, personList.size())
0 ~ personList.size() - 1 까지 숫자를 넘김
.mapToObj(personList::get)
personList.get(i) 요소를 Object형으로 변환해 다음 stream으로 전달
reduce
/* ageList 에서 마지막 요소 값 반환 */
Integer lastAge = ageList.stream()
.reduce((age1, age2) -> age2)
.get();
디렉토리 안의 파일 경로 접근하기
Path dirPath = Paths.get("/");
/* 디렉토리의 .txt 파일 경로만 가지고 작업 */
Files.walk(dirPath).filter(path -> path.toString().endsWith(".txt")).forEach(path ->
doFileWork(path)
);
.filter(path -> path.toString().endsWith(".txt"))
".txt"로 끝나는 경로만 doFileWork() 실행
전체 코드 참고
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Slf4j
class StreamTests {
@Test
void stream() {
/* 배열 출력 */
String[] alphabetArr = new String[]{"A", "B", "C"};
Arrays.stream(alphabetArr)
.forEach(alphabet -> log.info(alphabet));
}
@Test
void person() {
List<Person> personList = new ArrayList<>();
personList.add(new Person());
/* 멀티 라인 */
personList.stream().forEach(person -> {
person.setName("아무개");
person.setAge(13);
});
/* personList 중 한 요소라도 조건을 만족하면 true 반환 */
boolean anyMatch = personList.stream()
.anyMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
/* personList 중 모든 요소가 조건을 만족하면 true 반환 */
boolean allMatch = personList.stream()
.allMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
/* personList 중 모든 요소가 조건을 만족하지 않으면 true 반환 */
boolean noneMatch = personList.stream()
.noneMatch(person -> (person.getAge() == 13) && ("아무개".equals(person.getName())));
/* personList에서 filet 조건을 첫 번째로 만족하는 요소 반환 */
Person firstPerson = personList.stream()
.filter(person -> "아무개".equals(person.getName()))
.findFirst()
.get();
/* personList에서 age만 모아 List 로 반환 */
List<Integer> ageList = personList.stream()
.map(person -> person.getAge())
.collect(Collectors.toList());
/* personList에서 age만 모아 Set 으로 반환 */
Set<Integer> ageSet = personList.stream()
.map(person -> person.getAge())
.collect(Collectors.toSet());
/* personList에서 key가 name이고 value가 age인 Map 만들기 */
Map<String, Integer> personMap = personList.stream()
.collect(Collectors.toMap(Person::getName, Person::getAge));
/* personMap에서 value가 13인 요소의 key 리스트 반환 */
List<String> age13NameList = personMap.entrySet().stream()
.filter(person -> person.getValue() == 13)
.map(person -> person.getKey())
.collect(Collectors.toList());
/* personMap에서 value가 13인 요소의 key를 "," 로 이어붙이기 */
String names = personMap.entrySet().stream()
.filter(person -> person.getValue() == 13)
.map(Map.Entry::getKey)
.collect(Collectors.joining(","));
/* personMap의 key인 name의 최대 글자 수 구하기 */
int nameMaxLength = personMap.keySet().stream()
.mapToInt(name -> name.length())
.max()
.getAsInt();
/* 나이 평균 구하기 */
double ageAvg = ageList.stream()
.filter(Objects::nonNull)
.mapToDouble(age -> age)
.average()
.getAsDouble();
/* personList에서 짝수 인덱스 요소만 리스트로 반환 */
List<Person> subPersonList = IntStream.range(0, personList.size())
.filter(i -> i % 2 == 0)
.mapToObj(personList::get)
.collect(Collectors.toList());
/* ageList 에서 마지막 요소 값 반환 */
Integer lastAge = ageList.stream()
.reduce((age1, age2) -> age2)
.get();
}
@NoArgsConstructor @AllArgsConstructor @Setter @Getter
private class Person {
private String name;
private Integer age;
}
@Test
public void fileWalking() throws IOException {
Path dirPath = Paths.get("/");
/* 디렉토리의 .txt 파일 경로만 가지고 작업 */
Files.walk(dirPath).filter(path -> path.toString().endsWith(".txt")).forEach(path ->
doFileWork(path)
);
}
private void doFileWork(Path path) {}
}
글 읽어주셔서 언제나 감사합니다. 좋은 피드백, 개선 피드백 너무나도 환영합니다.
'SearchDeveloper > Java' 카테고리의 다른 글
ListenableFuture 의 Callback Hell 해결하기 (0) | 2023.05.03 |
---|---|
[JPA] 영속성 컨텍스트(Persistence Context) : 엔티티 관리 공간 (0) | 2022.10.03 |
Java 애플리케이션 메모리 누수(Memory leak) 잡기 - jstat, MAT (0) | 2022.10.02 |
Java 에서 테스트용 도커 컨테이너 띄우는 법 : TestContainer (4) | 2022.06.21 |
[번역] Pro Java Programming - 자바 아키텍쳐 (0) | 2020.10.18 |