일반 값들, 배열, 파일, 함수를 이용해서 무한 스트림 등 다양한 방식으로 스트림을 생성 가능하다.

 

값으로 스트림 생성

이전 글들에서 계속 예제를 위해 생성했던 Game List 도 아래와 같이 Stream.of 메서드를 이용해서 생성할 수 있다.

아래는 대문자로 요소를 변환해서 각각 출력하는 예제이다.

Stream<String> st = Stream.of("Dia1", "Dia2", "DIA3", "Call 1", "Call 2");
st.map(String::toUpperCase).forEach(System.out::println);
Stream<String> emStream = Stream.empty();
emStream.map(String::toUpperCase).forEach(System.out::println);

결과값

DIA1
DIA2
DIA3
CALL 1
CALL 2

 

Null 이 될 수 있는 객체로 생성

환경 변수를 가져올 때 값이 없으면 null 이 될 수 있는데 ofNullable 메서드를 사용하여 처리 가능하다.

Stream<String> values = Stream.of("config", "home", "user")
						.flatMap(key -> Stream.ofNullable(System.getProperty(key)));

 

배열로 스트림 생성

int[] numArr = {2,3,4,5};
int res = Arrays.stream(numArr).sum();
System.out.println(res);

결과값

14

 

파일로 스트림 생성

파일을 열어 고유 단어 수를 계산하는 예제이다.

long words =0;
try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
	words = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count(); 	
} catch (IOException e) {
	e.printStackTrace();
}

 

함수로 무한 스트림 생성

Stream의 iterate, genetate 메서드를 사용하여 무한 스트림을 만들 수 있다.

무한 스트림은 고정된 컬렉션에 고정된 크기가 아니라 크기가 고정되지 않은 스트림이다.

 

아래 iterate 예제는 초기값 1로 시작하여 1씩 누적 연산해 나가는 예제이다.

첫 번째 코드는 무한 생성되는 것을 확인 가능하다. 

Stream.iterate(1, n -> n+1).forEach(System.out::println); // 무한이 생성.
Stream.iterate(1, n -> n+1).limit(10).forEach(System.out::println); // 10개로 제한 생성.

 

아래 generate 예제이다.

iterate 와는 달리 연속적으로 값을 계산하지 않고 인수로 Supplier <T>를 받아 새로운 값을 생성한다.

Stream.generate(Math::random).forEach(System.out::println);
Stream.generate(Math::random).limit(10).forEach(System.out::println);

 

'Java > Stream' 카테고리의 다른 글

Collector 그룹화  (0) 2022.11.01
Collector 요약  (0) 2022.10.28
기본형 특화 스트림  (0) 2022.10.27
리듀싱  (0) 2022.10.26
검색과 매칭  (0) 2022.10.26

자바 8 에서는 박싱 비용을 피할 수 있게  IntStream, DoubleStream, LongStream 기본형 특화 스트림을 제공한다. 

스트림을 특화 스트림으로 변환할 때 mapToInt, mapToDouble, mapToLong 세 가지 메소드를 지원해준다.

map 같은 기능이지만 Stream<T>대신 특화된 스트림을 반환한다.

 

Game 객체 리스트를 생성.

List<Game> games = Arrays.asList(
		new Game("CALL 1", 20000)
		, new Game("DIA 3", 30000)
		, new Game("DIA 2", 40000)
		, new Game("DIA 1", 50000)
);

 

기본형 특화 스트림

숫자 스트림으로 매핑했다가 다시 객체 스트림으로 복원.

sum, max, min 같은 메서드 등 리듀상 연산 수행 메서드도 제공한다.

int price = games.stream().mapToInt(Game::getPrice).sum(); // 특화 스트림으로 변환해서 sum 메서드 사용
System.out.println(price);
		
IntStream intStream = games.stream().mapToInt(Game::getPrice); 
Stream<Integer> stream = intStream.boxed(); // 객체 스트림으로 복원

기본값이 없는 경우 Optional 객체 역시 기본형 특화 스트림이 제공된다.

OptionalInt, OptionalDouble, OptionalLong

OptionalInt maxPrice = games.stream().mapToInt(Game::getPrice).max();
int max = maxPrice.orElse(0); // 기본값 명시적 설정

 

 

숫자 범위

자바 8 에서는 IntStream 과 LongStream에서 range와 rangeClosed 라는 정적 메서드 제공.

두 메서드 모두 첫 번째 인수로 시작값, 두 번째 인수로 종료 값을 갖는다.

차이점은 range 메서드는 결과에 시작값과 종료값이 포함되지 않고 rangeClosed는 포함된다는 점이 다르다.

아래는 피타고라스 정리를 1 ~ 100 범위에서 가능한 조합을 결과 값으로 반환하는 코드이다.

Stream<int[]> pythago = IntStream.rangeClosed(1, 100).boxed()
				.flatMap(a -> IntStream.rangeClosed(a, 100)
				.filter(b -> Math.sqrt(a*a + b*b) % 1 == 0)
				.mapToObj(b -> new int[]{a, b, (int)Math.sqrt(a*a + b*b)}));
                
pythago.limit(5).forEach(t -> System.out.println(t[0] + "," + t[1] + "," + t[2]));

결과값

limt 으로 5개만 출력하게 제한을 걸었다.

3,4,5
5,12,13
6,8,10
7,24,25
8,15,17

 

'Java > Stream' 카테고리의 다른 글

Collector 요약  (0) 2022.10.28
스트림 생성  (0) 2022.10.27
리듀싱  (0) 2022.10.26
검색과 매칭  (0) 2022.10.26
map과 flatMap  (0) 2022.10.17

스트림 모든 스트림 요소를 처리해서 값으로 도출 하는 것을 지원하는 reduce 메서드를 제공.

 

예제에서 사용할 숫자 객체 리스트 생성하고 각 요소들을 합산하는 예제를 작성해보았다.

List<Integer> numbers = Arrays.asList(1,2,3,4,5);
int sum = 0;
for(int t : numbers) {
	sum += t;
}

결과값

15

 

누적 반복 연산을 하는 것을 reduce 메서드를 사용해서 간단하게 처리 가능하다.

reduce 메서드의 첫번째 인수는 초기값, 두 번째 인수는 두 요소를 조합해서 새로운 값을 만드는 BinaryOperator<T> 

int sum = numbers.stream().reduce(0, (a,b) -> a+b);

결과값

15

 

초기값 없이 처리도 가능하나 이때 반환 값이 Optional 객체이다.

Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a+b));	
System.out.println(sum.get());

 

최댓값과 최솟값도 reduce를 사용해서 다음과 같이 쉽게 처리가 가능하다.

Optional<Integer> min = numbers.stream().reduce(Integer::min);
System.out.println(min.get());

결과값

1

 

Optional<Integer> max = numbers.stream().reduce(Integer::max);
System.out.println(max.get());

결과값

5

'Java > Stream' 카테고리의 다른 글

스트림 생성  (0) 2022.10.27
기본형 특화 스트림  (0) 2022.10.27
검색과 매칭  (0) 2022.10.26
map과 flatMap  (0) 2022.10.17
필터링 및 슬라이싱  (0) 2022.10.10

스트림 API는 특정 속성이 데이터 집합에 존재 여부를 검색하는데 유용한

allMatch, anyMatch, noneMatch, findFirst, findAny 등의 메서드를 제공.

 

예제를 작성하기에 앞서 공통으로 사용할 games 리스트를 생성.

// 게임 데이터를 담는 리스트 생성.
List<Game> games = Arrays.asList(
	 new Game("CALL 1", 20000)
	,new Game("DIA 3", 30000)
	, new Game("DIA 2", 40000)
	, new Game("DIA 1", 50000)
);

 

anyMatch 

적어도 한 요소와 프레디케이트와 일치하는지 확인하는 메서드.

// 적어도 하나라도 일치하는지 불리언 반환하므로 최종연산
if(games.stream().anyMatch(game -> game.getName().startsWith("CALL"))) {
	System.out.println("The game is CALL series");
}

 

결과값

CALL 1이 일치하는 요소 이므로 아래의 결과값 출력.

The game is CALL series

 

allMatch

모든 요소가 주어진 프레디케이트와 일치하는지 검사.

// 모든 요소와 일치하는지 검사
if(games.stream().allMatch(game -> game.getName().startsWith("CALL"))) {
	System.out.println("The game is CALL series");
}

 

결과값

CALL 1 외에는 전부 DIA 시리즈이므로 일치하는 것이 없어 출력되는 것이 없음.

 

noneMatch

모든 요소가 주어진 프레디케이트와 일치하는지 않는지 검사.

if(games.stream().noneMatch(game -> game.getName().startsWith("STAR"))) {
	System.out.println("There is no Star series on this list of games");
}

 

결과값

요소 중에 STAR 시리즈는 없으므로 아래와 같은 결과가 출력.

There is no Star series on this list of games

 

 

findAny

현재 스트림의 임의의 요소를  Optional 객체로 반환.

Optional은 자바 8 에서 추가 된 기능으로 간단하게 활용도를 설명하면 null 확인 관련 버그를 피하는데 유용하다.

Optional에 대해서는 추후에 따로 글을 작성해보겠습니다.

Optional<Game> result = games.stream()
			.filter(game -> game.getName().startsWith("DIA"))
			.findAny();
System.out.println(result.get().getName());

 

결과값

요소 중에 랜덤으로 출력.

 

findFirst

첫번째 요소를 찾아서 Optional 객체로 반환.

Optional<Game> result = games.stream()
			.filter(game -> game.getName()
			.startsWith("DIA")).findFirst();
System.out.println(result.get().getName());

 

결과값

첫번째 요소는 DIA 3 이므로 아래와 같은 결과 출력.

DIA 3

 

 

'Java > Stream' 카테고리의 다른 글

기본형 특화 스트림  (0) 2022.10.27
리듀싱  (0) 2022.10.26
map과 flatMap  (0) 2022.10.17
필터링 및 슬라이싱  (0) 2022.10.10
정의 및 특징  (0) 2022.10.03

스트림 API의 map과 flatMap 메서드는 특정 데이터를 선택 가능하게 기능을 제공.

 

스트림 map

List<Game> games = Arrays.asList(
	new Game("CALL 1", 20000)
	, new Game("DIA 1", 30000)
	, new Game("DIA 2", 40000)
	, new Game("DIA 3", 50000)
);

객체 데이터를 생성 후에 간단하게 리스트 요소들의 게임명을 가져오는 map에 예제.

List<String> gameNameList = games.stream()
				.map(Game::getName)
				.collect(toList());
		
gameNameList.stream().forEach(name -> System.out.println(name));

만약에 각 요소들의 게임명의 길이가 필요하다면 아래와 같이 체이닝 처리할 수 있다.

List<Integer> gameNameLengthList = games.stream()
				.map(Game::getName)
				.map(String::length)
				.collect(toList());
		
gameNameLengthList.stream().forEach(itemLength -> System.out.println(itemLength));

 

결과값

6
5
5
5

 

스트림 flatMap

메서드 map을 이용해 리스트의 중복을 제거한 각 단어의 길이를 반환한다고 하자.

아래와 같이 작성한다면 리턴 값은 Stream<String[]>이 된다.

각각의 스트림으로 반환이 되는 것이다.

List <String> words = Arrays.asList("Goodbye", "World");
		
List<String[]> uniqueCharList = words.stream()
.map(word -> word.split(""))
.distinct()
.collect(toList());

하나의 스트림으로 반환하고 싶다면 어떻게 해야 할까?

아래와 같이 작성해도 결국 Stream 리스트가 반환된다.

 

List<Stream<String>> uniqueCharList = words.stream()
		.map(word -> word.split(""))
		.map(Arrays::stream)
		.distinct()
		.collect(toList());​

flatMap을 사용하면 각 배열을 스트림이 아니라 스트림의 콘텐츠로 맵핑한다.

앞의 예제와는 다르게 하나의 스트림을 반환한다.

List<String> uniqueCharList = words.stream()
		.map(word -> word.split(""))
		.flatMap(stream -> Arrays.stream(stream))
		.distinct()
		.collect(toList());
		
uniqueCharList.stream().forEach(System.out::println);

 

결과값

GodbyeWrl

 

'Java > Stream' 카테고리의 다른 글

기본형 특화 스트림  (0) 2022.10.27
리듀싱  (0) 2022.10.26
검색과 매칭  (0) 2022.10.26
필터링 및 슬라이싱  (0) 2022.10.10
정의 및 특징  (0) 2022.10.03

스트림 필터링

스트림에서 지원하는 filter 메서드 사용.

프리디케이트를 인수로 받아서 프레디케이트와 일치하는 모든 요소를 포함하는 스트림을 반환.

List<Integer> numArr = Arrays.asList(1,2,1,3,3,3,2,4,5);
numArr.stream()
	.filter(i -> i == 3)
	.forEach(System.out::println);

 

요소 중에 3인 요소들이 있으면 출력.

여기서 중복을 제거하는 고유 요소 필터링을 하고 싶다면 스트림에서 지원하는 distinct 메서드를 사용한다.

고유 여부는 스트림에서 만든 객체의 hashcode, equals로 결정.

List<Integer> numArr = Arrays.asList(1,2,1,3,3,3,2,4,5);
numArr.stream()
	.filter(i -> i == 3)
	.distinct()
	.forEach(System.out::println);

 

스트림 슬라이싱

프리디케이트를 이용한 슬라이싱, 스트림 요소 무시, 축소 등 다양한 방법으로 요소를 선택하거나 스킵할 수 있다.

아래 예제는 단순히 게임 목록에 대한 가격 필터링을 한 예제이다.

List<Game> games = Arrays.asList(
	new Game("CALL 1", 20000)
	, new Game("DIA 1", 30000)
	, new Game("DIA 2", 40000)
	, new Game("DIA 3", 50000)
);
List<Game> filteredGame = games.stream()
			.filter(game -> game.getPrice() < 40000)
			.collect(toList());

만약 filter 메서드의 요소를 만족했을 때 작업을 중단하고 싶다면 takeWhile, dropWhile을 사용하면 된다.

사용하지 않는 경우 모든 요소만큼 작업을 수행하므로 요소 목록 크기가 크다면 그만큼 낭비가 된다.

 

takewhile 메서드

프레디케이트가 처음으로 참이 되는 지점까지 발견된 요소를 반환.

List<Game> takeWhileGame = games.stream()
		.takeWhile(game -> game.getPrice() < 40000)
		.collect(toList());

 

dropwhile 메서드

프레디케이트가 처음으로 거짓이 되는 지점까지 발견된 요소를 버림.

List<Game> dropWhileGame = games.stream()
		.dropWhile(game -> game.getPrice() < 40000)
		.collect(toList());

 

limit 메서드

주어진 값 이하의 크기를 갖는 새로운 스트림을 반환.

List<Game> dropWhileGame = games.stream()
		.dropWhile(game -> game.getPrice() < 40000)
       		.limit(1)
		.collect(toList());

 

skip 메서드

처음 N개 요소를 제외한 스트림을 반환.

List<Game> dropWhileGame = games.stream()
		.dropWhile(game -> game.getPrice() < 40000)
       		.skip(2)
		.collect(toList());


위에서 작성한 예제들의 요소 값들을 출력해보면 어떻게 동작하는지 짐작할 수 있습니다.

filteredGame.stream().forEach(game -> System.out.println(game.getName()));
Sytem.out.println();
takeWhileGame.stream().forEach(game -> System.out.println(game.getName()));
Sytem.out.println();
dropWhileGame.stream().forEach(game -> System.out.println(game.getName()));

 

결과 값

CALL 1
DIA 1

CALL 1

DIA 1

 

'Java > Stream' 카테고리의 다른 글

기본형 특화 스트림  (0) 2022.10.27
리듀싱  (0) 2022.10.26
검색과 매칭  (0) 2022.10.26
map과 flatMap  (0) 2022.10.17
정의 및 특징  (0) 2022.10.03

+ Recent posts