Stream API 이해
1. 데이터 선별
- 조건에 따라 데이터를 선별하는 중간 연산입니다.
- 데이터 선별 예제
더보기
package lambdaExample; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 선별------------------"); DataSelect dataSelect = new DataSelect(); dataSelect.dataSelect(); } } class DataSelect { public void dataSelect () { ListClass listClass = new ListClass(); listClass.cities.add(new ExCity("Seoul", 0, 0, "02")); System.out.println("배열 추가 시"); for (ExCity city : listClass.cities) { System.out.println( city.getName() + " " + city.getArea() + " " + city.getPopulation() + " " + city.getAreaCode()); } List<ExCity> streamNameList = listClass.cities.stream() .filter(city -> city.getArea() > 600) // 데이터 필터링 .distinct() // 중복 제거 .collect(Collectors.toList()); System.out.println("\n중복 제거 시"); for (ExCity city : streamNameList) { System.out.println( city.getName() + " " + city.getArea() + " " + city.getPopulation() + " " + city.getAreaCode()); } } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 선별------------------ 배열 추가 시 Seoul 605.2 9720846 02 Incheon 1063.3 2947217 032 Ulsan 1062.0 1142190 052 Daegu 883.5 2427954 053 Gwangju 501.1 1455048 062 Busan 770.1 3404423 051 Seoul 0.0 0 02 중복 제거 시 Seoul 605.2 9720846 02 Incheon 1063.3 2947217 032 Ulsan 1062.0 1142190 052 Daegu 883.5 2427954 053 Busan 770.1 3404423 051 */
- Stream::filter는 Predicate를 인자로 받습니다.
- 중복 요소를 제거하고 싶다면 Stream::distinct를 사용합니다.
2. 데이터 개수 조절
- 스트림 데이터를 자르거나 특정 요소만 성택합니다.
- 개수 제한 Stream::limit으로 개수 조절이 가능합니다.
- 건너 뛰기 Stream::skip으로 n개를 건너뛸 수 있습니다.
- 데이터 개수 조절 예제
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 개수 조절------------------"); DataCountControl dataCountControl = new DataCountControl(); dataCountControl.dataCountControl(); } } class DataCountControl { public void dataCountControl() { ListClass listClass = new ListClass(); // limit을 이용하여 수집 개수 조절 List<String> streamLimit = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .sorted(Comparator.comparing(ExCity::getArea)) .map(ExCity::getName) .limit(2) // 최소 2개의 원소만 반환합니다. .collect(Collectors.toList()); System.out.println("Stream Limit"); System.out.println(streamLimit); // skip을 이용하여 데이터 건너뛰기 List<String> streamSkip = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .sorted(Comparator.comparing(ExCity::getArea)) .map(ExCity::getName) .skip(1) // 첫 번째 원소는 뛰어넘습니다. .collect(Collectors.toList()); System.out.println("Stream Skip"); System.out.println(streamSkip); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 개수 조절------------------ Stream Limit [Daegu, Ulsan] Stream Skip [Ulsan, Incheon] */
- 특정 조건에 부합하는 데이터만 선택합니다.
- 전제조건으로 자바 9버전 이상부터 지원됩니다.
- Stream::takeWhile은 스트림을 순회하면서 false가 되는 순간 남은 데이터를 버립니다.
- Stream::dropWhile은 스트림을 순회하면서 true가 되는 순간 남은 데이터를 버립니다.
- Stream::filter와 차이점은 필터는 조건에 맞는 데이터만 선택하지만, takeWhile과 dropWhile은 데이터를 버립니다.
- 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 선별2------------------"); DataSelect2 dataSelect2 = new DataSelect2(); dataSelect2.dataSelect2(); System.out.println("\n------------------Stream 데이터 선별3------------------"); DataSelect3 dataSelect3 = new DataSelect3(); dataSelect3.dataSelect3(); } } class DataSelect3 { public void dataSelect3 () { ListClass listClass = new ListClass(); // dropWhile은 true가 되면 멈추고 나머지 데이터는 버립니다. List<String> streamSelectAsc = listClass.cities.stream() .sorted(Comparator.comparing(ExCity::getArea)) .dropWhile(exCity -> exCity.getArea() > 700) .map(ExCity::getName) .collect(Collectors.toList()); System.out.println("dropWhile 오름차순 정렬"); System.out.println(streamSelectAsc); List<String> streamSelectDesc = listClass.cities.stream() .sorted(Comparator.comparing(ExCity::getArea).reversed()) .dropWhile(exCity -> exCity.getArea() > 700) .map(ExCity::getName) .collect(Collectors.toList()); System.out.println("dropWhile 내림차순 정렬"); System.out.println(streamSelectDesc); } } class DataSelect2 { public void dataSelect2 () { ListClass listClass = new ListClass(); // takeWhile은 false가 되면 멈추고 나머지 데이터는 버립니다. List<String> streamSelectAsc = listClass.cities.stream() .sorted(Comparator.comparing(ExCity::getArea)) .takeWhile(exCity -> exCity.getArea() > 700) .map(ExCity::getName) .collect(Collectors.toList()); System.out.println("takeWhile 오름차순 정렬"); System.out.println(streamSelectAsc); // area를 역순 정렬하여 비교해 보겠습니다. List<String> streamSelectDesc = listClass.cities.stream() .sorted(Comparator.comparing(ExCity::getArea).reversed()) .takeWhile(exCity -> exCity.getArea() > 700) .map(ExCity::getName) .collect(Collectors.toList()); System.out.println("takeWhile 내림차순 정렬"); System.out.println(streamSelectDesc); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 선별2------------------ takeWhile 오름차순 정렬 [] takeWhile 내림차순 정렬 [Incheon, Ulsan, Daegu, Busan] ------------------Stream 데이터 선별3------------------ dropWhile 오름차순 정렬 [Gwangju, Seoul, Busan, Daegu, Ulsan, Incheon] dropWhile 내림차순 정렬 [Seoul, Gwangju] */
3. 데이터 변환
- Stream::map은 스트림 원소를 변환합니다.
- 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 변환------------------"); DataConversion dataConversion = new DataConversion(); dataConversion.dataConversion(); } } class DataConversion { public void dataConversion () { ListClass listClass = new ListClass(); List<String> streamMap = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .sorted(Comparator.comparing(ExCity::getArea)) .map(exCity -> exCity.getName()) // .map(ExCity::getName) 위와 똑같은 역할입니다. .collect(Collectors.toList()); System.out.println("Stream Map"); System.out.println(streamMap); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 변환------------------ Stream Map [Daegu, Ulsan, Incheon] */
1. 단일 스트림으로 변환
- Stream::flatMap은 배열의 데이터를 문자열 하나로 만들거나 문자열을 문자 단위로 분해하는 과정이 필요할 때 사용합니다.
- Stream::flatMap 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 변환2------------------"); DataConversion2 dataConversion2 = new DataConversion2(); dataConversion2.dataConversion2(); } } class DataConversion2 { public void dataConversion2 () { ListClass listClass = new ListClass(); List<String> streamMap2 = listClass.cities.stream() .map(ExCity::getAreaCode) .collect(Collectors.toList()); System.out.println("Stream Map2"); System.out.println(streamMap2); List<String> streamSplit = streamMap2.stream() .map(areaCode -> areaCode.split("")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList()); System.out.println("Stream Split"); System.out.println(streamSplit); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 변환2------------------ Stream Map2 [02, 032, 052, 053, 062, 051] Stream Split [0, 2, 3, 5, 6, 1] */
4. 데이터 일치 여부
- boolean을 반환하는 연산입니다.
- Short Circuit Evaluation 기법이 적용되어 값을 즉시 반환할 수 있는 상태가 되면 남은 원소를 확인하지 않습니다.
- Short Circuit 예시
if (true || false) { ... } if (false && true) { ... }
- Stream::anyMatch는 검색 조건에 맞는 원소가 1개 이상인 경우 true를 반환합니다.
- Stream::allMatch는 모든 검색 조건이 일치해야 true를 반환합니다.
- Stream::noneMatch는 모든 원소가 검색 조건에 일치하지 않아야 true를 반환합니다.
- 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 일치 여부------------------"); DataMatch dataMatch = new DataMatch(); dataMatch.dataMatch(); } } class DataMatch { public void dataMatch () { ListClass listClass = new ListClass(); boolean streamAnyMatch = listClass.cities.stream() .anyMatch(exCity -> exCity.getArea() > 1000); boolean streamAnyMatch2 = listClass.cities.stream() .anyMatch(exCity -> exCity.getArea() > 2000); System.out.println("Stream Any Math 1000"); System.out.println(streamAnyMatch); System.out.println("Stream Any Math 2000"); System.out.println(streamAnyMatch2); boolean streamAllMatch = listClass.cities.stream() .allMatch(exCity -> exCity.getArea() > 100); boolean streamAllMatch2 = listClass.cities.stream() .allMatch(exCity -> exCity.getArea() > 1000); System.out.println("Stream All Match 100"); System.out.println(streamAllMatch); System.out.println("Stream All Match 1000"); System.out.println(streamAllMatch2); boolean streamNoneMatch = listClass.cities.stream() .noneMatch(exCity -> exCity.getArea() > 1000); boolean streamNoneMatch2 = listClass.cities.stream() .noneMatch(exCity -> exCity.getArea() > 2000); System.out.println("Stream None Match 1000"); System.out.println(streamNoneMatch); System.out.println("Stream None Match 2000"); System.out.println(streamNoneMatch2); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 일치 여부------------------ Stream Any Math 1000 true Stream Any Math 2000 false Stream All Match 100 true Stream All Match 1000 false Stream None Match 1000 false Stream None Match 2000 true */
5. 데이터 검색
- 검색 메서드를 사용하면 스트림 파이트라인에서 적절한 데이터를 찾습니다.
- 또한 데이터를 찾는 순간 검색이 종료되는 Short Circuit 기법이 적용됩니다.
- 검색 조건에 부합하는 데이터가 없을 수도 있습니다.
- 따라서 반환 시엔 Optional을 사용합니다.
- Stream::findAny는 검색 조건에 부합하는 임의의 데이터를 반환합니다.
- Stream::findFirst는 검색 조건에 부합하는 첫 번째 데이터를 반환합니다.
- 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 데이터 검색------------------"); DataSearch dataSearch = new DataSearch(); dataSearch.dataSearch(); } } class DataSearch { public void dataSearch () { ListClass listClass = new ListClass(); Optional<ExCity> findAny = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 500) .findAny(); System.out.println("Stream Find Any"); System.out.println(findAny.get().getName()); Optional<ExCity> findFirst = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 500) .findFirst(); System.out.println("Stream Find First"); System.out.println(findFirst.get().getName()); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 데이터 검색------------------ Stream Find Any Seoul Stream Find First Seoul */
6. 데이터 연산
- 랜덤 숫자가 담긴 배열의 총 합을 스트림을 활용해 보겠습니다.
- Stream::reduce는 값을 연쇄적으로 계산할 때 사용합니다.
- reduce는 (int), IntBinaryOperator를 매개변수로 받습니다.
- 첫 번째 int는 초기값으로, 생략이 가능합니다.
- IntBinaryOperator는 두 개의 int형 매개변수를 받아 int를 반환하는 함수형 인터페이스입니다.
1. for loop 활용과 Stream 활용
더보기
package lambdaExample;
import java.nio.file.spi.FileSystemProvider;
import java.util.*;
import java.util.stream.Collectors;
import javax.xml.transform.Source;
public class LambdaBasic2 {
public static void main(String[] args) {
System.out.println("\n------------------Stream 데이터 연산------------------");
DataOperation dataOperation = new DataOperation();
dataOperation.dataOperation();
}
}
class DataOperation {
public void dataOperation () {
Random random = new Random();
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = random.nextInt(100);
}
int sum = 0;
for (int num : arr) {
sum += num;
}
System.out.println("일반 연산");
System.out.println(sum);
int streamSum = Arrays.stream(arr)
.reduce(0, Integer::sum);
System.out.println("스트림 연산");
System.out.println(streamSum);
}
}
class ExCity {
private String name;
private double area; // 면적
private int population; // 인구
private String areaCode; // 지역 번호
// 필드 전체를 파라미터로 받는 생성자
public ExCity (String name, double area, int population, String areaCode) {
this.name = name;
this.area = area;
this.population = population;
this.areaCode = areaCode;
}
// getter
public String getName () {
return name;
}
public double getArea () {
return area;
}
public int getPopulation () {
return population;
}
public String getAreaCode () {
return areaCode;
}
}
class ListClass {
List<ExCity> cities = new ArrayList<>(
Arrays.asList(
new ExCity("Seoul", 605.2, 9720846, "02"),
new ExCity("Incheon", 1063.3, 2947217, "032"),
new ExCity("Ulsan", 1062, 1142190, "052"),
new ExCity("Daegu", 883.5, 2427954, "053"),
new ExCity("Gwangju", 501.1, 1455048, "062"),
new ExCity("Busan", 770.1, 3404423, "051"))
);
}
/*
출력
------------------Stream 데이터 연산------------------
일반 연산
4777
스트림 연산
4777
*/
7. 최종 연산
- 최종 연산은 자료형, 컬렉션, void를 반환합니다.
- 사용 예시
더보기
package lambdaExample; import java.nio.file.spi.FileSystemProvider; import java.util.*; import java.util.stream.Collectors; import javax.xml.transform.Source; public class LambdaBasic2 { public static void main(String[] args) { System.out.println("\n------------------Stream 최종 연산------------------"); FinalStream finalStream = new FinalStream(); finalStream.finalStream(); } } class FinalStream { public void finalStream() { ListClass listClass = new ListClass(); List<String> streamList = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .sorted(Comparator.comparing(ExCity::getArea)) .map(ExCity::getName) .collect(Collectors.toList()); System.out.println("\nStream List"); System.out.println(streamList); Map<String, List<ExCity>> streamMap = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .collect(Collectors.groupingBy(ExCity::getName)); System.out.println("\nStream Map"); streamMap.forEach((city, exCities) -> { System.out.println("City : " + city); exCities.forEach(exCity -> System.out.println( exCity.getName() + " " + exCity.getArea() + " " + exCity.getAreaCode() + " " + exCity.getPopulation() )); }); Set<ExCity> streamSet = listClass.cities.stream() .filter(exCity -> exCity.getArea() > 800) .collect(Collectors.toSet()); System.out.println("\nStream Set"); for (ExCity exCity : streamSet) { System.out.println( exCity.getName() + " " + exCity.getArea() + " " + exCity.getAreaCode() + " " + exCity.getPopulation()); } System.out.println("\nStream Count"); System.out.println(listClass.cities.stream().count()); System.out.println("\nStream forEach"); listClass.cities.stream().map(ExCity::getName).forEach(System.out::println); } } class ExCity { private String name; private double area; // 면적 private int population; // 인구 private String areaCode; // 지역 번호 // 필드 전체를 파라미터로 받는 생성자 public ExCity (String name, double area, int population, String areaCode) { this.name = name; this.area = area; this.population = population; this.areaCode = areaCode; } // getter public String getName () { return name; } public double getArea () { return area; } public int getPopulation () { return population; } public String getAreaCode () { return areaCode; } } class ListClass { List<ExCity> cities = new ArrayList<>( Arrays.asList( new ExCity("Seoul", 605.2, 9720846, "02"), new ExCity("Incheon", 1063.3, 2947217, "032"), new ExCity("Ulsan", 1062, 1142190, "052"), new ExCity("Daegu", 883.5, 2427954, "053"), new ExCity("Gwangju", 501.1, 1455048, "062"), new ExCity("Busan", 770.1, 3404423, "051")) ); } /* 출력 ------------------Stream 최종 연산------------------ Stream List [Daegu, Ulsan, Incheon] Stream Map City : Incheon Incheon 1063.3 032 2947217 City : Ulsan Ulsan 1062.0 052 1142190 City : Daegu Daegu 883.5 053 2427954 Stream Set Incheon 1063.3 032 2947217 Ulsan 1062.0 052 1142190 Daegu 883.5 053 2427954 Stream Count 6 Stream forEach Seoul Incheon Ulsan Daegu Gwangju Busan */
8. 전체 코드
더보기
package lambdaExample;
import java.nio.file.spi.FileSystemProvider;
import java.util.*;
import java.util.stream.Collectors;
import javax.xml.transform.Source;
public class LambdaBasic2 {
public static void main(String[] args) {
System.out.println("\n------------------Stream 데이터 선별------------------");
DataSelect dataSelect = new DataSelect();
dataSelect.dataSelect();
System.out.println("\n------------------Stream 데이터 선별2------------------");
DataSelect2 dataSelect2 = new DataSelect2();
dataSelect2.dataSelect2();
System.out.println("\n------------------Stream 데이터 선별3------------------");
DataSelect3 dataSelect3 = new DataSelect3();
dataSelect3.dataSelect3();
System.out.println("\n------------------Stream 데이터 개수 조절------------------");
DataCountControl dataCountControl = new DataCountControl();
dataCountControl.dataCountControl();
System.out.println("\n------------------Stream 데이터 변환------------------");
DataConversion dataConversion = new DataConversion();
dataConversion.dataConversion();
System.out.println("\n------------------Stream 데이터 변환2------------------");
DataConversion2 dataConversion2 = new DataConversion2();
dataConversion2.dataConversion2();
System.out.println("\n------------------Stream 데이터 일치 여부------------------");
DataMatch dataMatch = new DataMatch();
dataMatch.dataMatch();
System.out.println("\n------------------Stream 데이터 검색------------------");
DataSearch dataSearch = new DataSearch();
dataSearch.dataSearch();
System.out.println("\n------------------Stream 데이터 연산------------------");
DataOperation dataOperation = new DataOperation();
dataOperation.dataOperation();
System.out.println("\n------------------Stream 최종 연산------------------");
FinalStream finalStream = new FinalStream();
finalStream.finalStream();
}
}
class FinalStream {
public void finalStream() {
ListClass listClass = new ListClass();
List<String> streamList = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.sorted(Comparator.comparing(ExCity::getArea))
.map(ExCity::getName)
.collect(Collectors.toList());
System.out.println("\nStream List");
System.out.println(streamList);
Map<String, List<ExCity>> streamMap = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.collect(Collectors.groupingBy(ExCity::getName));
System.out.println("\nStream Map");
streamMap.forEach((city, exCities) -> {
System.out.println("City : " + city);
exCities.forEach(exCity -> System.out.println(
exCity.getName() + " " +
exCity.getArea() + " " +
exCity.getAreaCode() + " " +
exCity.getPopulation()
));
});
Set<ExCity> streamSet = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.collect(Collectors.toSet());
System.out.println("\nStream Set");
for (ExCity exCity : streamSet) {
System.out.println(
exCity.getName() + " " +
exCity.getArea() + " " +
exCity.getAreaCode() + " " +
exCity.getPopulation());
}
System.out.println("\nStream Count");
System.out.println(listClass.cities.stream().count());
System.out.println("\nStream forEach");
listClass.cities.stream().map(ExCity::getName).forEach(System.out::println);
}
}
class DataOperation {
public void dataOperation () {
Random random = new Random();
int[] arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = random.nextInt(100);
}
int sum = 0;
for (int num : arr) {
sum += num;
}
System.out.println("일반 연산");
System.out.println(sum);
int streamSum = Arrays.stream(arr)
.reduce(0, Integer::sum);
System.out.println("스트림 연산");
System.out.println(streamSum);
}
}
class DataSearch {
public void dataSearch () {
ListClass listClass = new ListClass();
Optional<ExCity> findAny = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 500)
.findAny();
System.out.println("Stream Find Any");
System.out.println(findAny.get().getName());
Optional<ExCity> findFirst = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 500)
.findFirst();
System.out.println("Stream Find First");
System.out.println(findFirst.get().getName());
}
}
class DataMatch {
public void dataMatch () {
ListClass listClass = new ListClass();
boolean streamAnyMatch = listClass.cities.stream()
.anyMatch(exCity -> exCity.getArea() > 1000);
boolean streamAnyMatch2 = listClass.cities.stream()
.anyMatch(exCity -> exCity.getArea() > 2000);
System.out.println("Stream Any Math 1000");
System.out.println(streamAnyMatch);
System.out.println("Stream Any Math 2000");
System.out.println(streamAnyMatch2);
boolean streamAllMatch = listClass.cities.stream()
.allMatch(exCity -> exCity.getArea() > 100);
boolean streamAllMatch2 = listClass.cities.stream()
.allMatch(exCity -> exCity.getArea() > 1000);
System.out.println("Stream All Match 100");
System.out.println(streamAllMatch);
System.out.println("Stream All Match 1000");
System.out.println(streamAllMatch2);
boolean streamNoneMatch = listClass.cities.stream()
.noneMatch(exCity -> exCity.getArea() > 1000);
boolean streamNoneMatch2 = listClass.cities.stream()
.noneMatch(exCity -> exCity.getArea() > 2000);
System.out.println("Stream None Match 1000");
System.out.println(streamNoneMatch);
System.out.println("Stream None Match 2000");
System.out.println(streamNoneMatch2);
}
}
class DataConversion2 {
public void dataConversion2 () {
ListClass listClass = new ListClass();
List<String> streamMap2 = listClass.cities.stream()
.map(ExCity::getAreaCode)
.collect(Collectors.toList());
System.out.println("Stream Map2");
System.out.println(streamMap2);
List<String> streamSplit = streamMap2.stream()
.map(areaCode -> areaCode.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
System.out.println("Stream Split");
System.out.println(streamSplit);
}
}
class DataConversion {
public void dataConversion () {
ListClass listClass = new ListClass();
List<String> streamMap = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.sorted(Comparator.comparing(ExCity::getArea))
.map(exCity -> exCity.getName())
// .map(ExCity::getName) 위와 똑같은 역할입니다.
.collect(Collectors.toList());
System.out.println("Stream Map");
System.out.println(streamMap);
}
}
class DataCountControl {
public void dataCountControl() {
ListClass listClass = new ListClass();
// limit을 이용하여 수집 개수 조절
List<String> streamLimit = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.sorted(Comparator.comparing(ExCity::getArea))
.map(ExCity::getName)
.limit(2) // 최소 2개의 원소만 반환합니다.
.collect(Collectors.toList());
System.out.println("Stream Limit");
System.out.println(streamLimit);
// skip을 이용하여 데이터 건너뛰기
List<String> streamSkip = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 800)
.sorted(Comparator.comparing(ExCity::getArea))
.map(ExCity::getName)
.skip(1) // 첫 번째 원소는 뛰어넘습니다.
.collect(Collectors.toList());
System.out.println("Stream Skip");
System.out.println(streamSkip);
}
}
class DataSelect3 {
public void dataSelect3 () {
ListClass listClass = new ListClass();
// dropWhile은 true가 되면 멈추고 나머지 데이터는 버립니다.
List<String> streamSelectAsc = listClass.cities.stream()
.sorted(Comparator.comparing(ExCity::getArea))
.dropWhile(exCity -> exCity.getArea() > 700)
.map(ExCity::getName)
.collect(Collectors.toList());
System.out.println("dropWhile 오름차순 정렬");
System.out.println(streamSelectAsc);
List<String> streamSelectDesc = listClass.cities.stream()
.sorted(Comparator.comparing(ExCity::getArea).reversed())
.dropWhile(exCity -> exCity.getArea() > 700)
.map(ExCity::getName)
.collect(Collectors.toList());
System.out.println("dropWhile 내림차순 정렬");
System.out.println(streamSelectDesc);
}
}
class DataSelect2 {
public void dataSelect2 () {
ListClass listClass = new ListClass();
// takeWhile은 false가 되면 멈추고 나머지 데이터는 버립니다.
List<String> streamSelectAsc = listClass.cities.stream()
.sorted(Comparator.comparing(ExCity::getArea))
.takeWhile(exCity -> exCity.getArea() > 700)
.map(ExCity::getName)
.collect(Collectors.toList());
System.out.println("takeWhile 오름차순 정렬");
System.out.println(streamSelectAsc);
// area를 역순 정렬하여 비교해 보겠습니다.
List<String> streamSelectDesc = listClass.cities.stream()
.sorted(Comparator.comparing(ExCity::getArea).reversed())
.takeWhile(exCity -> exCity.getArea() > 700)
.map(ExCity::getName)
.collect(Collectors.toList());
System.out.println("takeWhile 내림차순 정렬");
System.out.println(streamSelectDesc);
}
}
class DataSelect {
public void dataSelect () {
ListClass listClass = new ListClass();
listClass.cities.add(new ExCity("Seoul", 0, 0, "02"));
System.out.println("배열 추가 시");
for (ExCity city : listClass.cities) {
System.out.println(
city.getName() + " " +
city.getArea() + " " +
city.getPopulation() + " " +
city.getAreaCode());
}
List<ExCity> streamSelect = listClass.cities.stream()
.filter(exCity -> exCity.getArea() > 600) // 데이터 필터링
.distinct() // 중복 제거
.collect(Collectors.toList());
System.out.println("\n중복 제거 시");
for (ExCity city : streamSelect) {
System.out.println(
city.getName() + " " +
city.getArea() + " " +
city.getPopulation() + " " +
city.getAreaCode());
}
}
}
class ExCity {
private String name;
private double area; // 면적
private int population; // 인구
private String areaCode; // 지역 번호
// 필드 전체를 파라미터로 받는 생성자
public ExCity (String name, double area, int population, String areaCode) {
this.name = name;
this.area = area;
this.population = population;
this.areaCode = areaCode;
}
// getter
public String getName () {
return name;
}
public double getArea () {
return area;
}
public int getPopulation () {
return population;
}
public String getAreaCode () {
return areaCode;
}
}
class ListClass {
List<ExCity> cities = new ArrayList<>(
Arrays.asList(
new ExCity("Seoul", 605.2, 9720846, "02"),
new ExCity("Incheon", 1063.3, 2947217, "032"),
new ExCity("Ulsan", 1062, 1142190, "052"),
new ExCity("Daegu", 883.5, 2427954, "053"),
new ExCity("Gwangju", 501.1, 1455048, "062"),
new ExCity("Busan", 770.1, 3404423, "051"))
);
}
/*
출력
------------------Stream 데이터 선별------------------
배열 추가 시
Seoul 605.2 9720846 02
Incheon 1063.3 2947217 032
Ulsan 1062.0 1142190 052
Daegu 883.5 2427954 053
Gwangju 501.1 1455048 062
Busan 770.1 3404423 051
Seoul 0.0 0 02
중복 제거 시
Seoul 605.2 9720846 02
Incheon 1063.3 2947217 032
Ulsan 1062.0 1142190 052
Daegu 883.5 2427954 053
Busan 770.1 3404423 051
------------------Stream 데이터 선별2------------------
takeWhile 오름차순 정렬
[]
takeWhile 내림차순 정렬
[Incheon, Ulsan, Daegu, Busan]
------------------Stream 데이터 선별3------------------
dropWhile 오름차순 정렬
[Gwangju, Seoul, Busan, Daegu, Ulsan, Incheon]
dropWhile 내림차순 정렬
[Seoul, Gwangju]
------------------Stream 데이터 개수 조절------------------
Stream Limit
[Daegu, Ulsan]
Stream Skip
[Ulsan, Incheon]
------------------Stream 데이터 변환------------------
Stream Map
[Daegu, Ulsan, Incheon]
------------------Stream 데이터 변환2------------------
Stream Map2
[02, 032, 052, 053, 062, 051]
Stream Split
[0, 2, 3, 5, 6, 1]
------------------Stream 데이터 일치 여부------------------
Stream Any Math 1000
true
Stream Any Math 2000
false
Stream All Match 100
true
Stream All Match 1000
false
Stream None Match 1000
false
Stream None Match 2000
true
------------------Stream 데이터 검색------------------
Stream Find Any
Seoul
Stream Find First
Seoul
------------------Stream 데이터 연산------------------
일반 연산
4777
스트림 연산
4777
------------------Stream 최종 연산------------------
Stream List
[Daegu, Ulsan, Incheon]
Stream Map
City : Incheon
Incheon 1063.3 032 2947217
City : Ulsan
Ulsan 1062.0 052 1142190
City : Daegu
Daegu 883.5 053 2427954
Stream Set
Incheon 1063.3 032 2947217
Ulsan 1062.0 052 1142190
Daegu 883.5 053 2427954
Stream Count
6
Stream forEach
Seoul
Incheon
Ulsan
Daegu
Gwangju
Busan
*/
'JAVA' 카테고리의 다른 글
[JAVA] - Stream API 이해 6 (0) | 2024.05.31 |
---|---|
[JAVA] - Stream API 이해 5 (0) | 2024.05.30 |
[JAVA] - Stream API 이해 3 (0) | 2024.05.28 |
[JAVA] - Stream API 이해 2 (0) | 2024.05.27 |
[JAVA] - Stream API 이해 1 (0) | 2024.05.25 |