CHAP05 - Modern-Java-in-Action/Online-Study GitHub Wiki
-
filter
: Predicate(boolean type)๋ฅผ ์ธ์๋ก ๋ฐ์์ ํ๋ ๋์ผ์ดํธ์ ์ผ์นํ๋ ๋ชจ๋ ์์๋ฅผ ํฌํจํ๋ ์คํธ๋ฆผ ๋ฐํ
List<Dish> vegetarianMenu = menu.stream()
.filter(Dish::isVegetarian)
.collect(toList());
-
distinct
: ๊ณ ์ ์์๋ก ์ด๋ฃจ์ด์ง ์คํธ๋ฆผ ๋ฐํ(๊ณ ์ ์ฌ๋ถ๋hashCode
,equals
๋ก ๊ฒฐ์ )
List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,6);
numbers.stream()
.filter(i->i%2 == 0)
.distinct()
.forEach(System.out::println);
-
takewhile
: ๋ฌดํ ์คํธ๋ฆผ์ ํฌํจํ ๋ชจ๋ ์คํธ๋ฆผ์ ํ๋ ๋์ผ์ดํธ๋ฅผ ์ ์ฉํด ์คํธ๋ฆผ์ ์ฌ๋ผ์ด์ค ํ ์ ์๋ค.
List<Dish> slicedMenu1 = specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)
.collect(toList());
-
dropwhile
: ํ๋ ๋์ผ์ดํธ๊ฐ ์ฒ์์ผ๋ก ๊ฑฐ์ง์ด ๋๋ ์ง์ ๊น์ง ๋ฐ๊ฒฌ๋ ์์๋ฅผ ๋ฒ๋ฆฐ๋ค.
List<Dish> slicedMenu2 = specialMenu.stream()
.dropWhile(dish -> dish.getCalories() < 320)
.collect(toList());
-
limit(n)
: ์ฃผ์ด์ง ๊ฐ ์ดํ์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ ์๋ก์ด ์คํธ๋ฆผ์ ๋ฐํ- ์ ๋ ฌ๋์ง ์์ ์คํธ๋ฆผ์๋ limit ์ฌ์ฉ ๊ฐ๋ฅ(์ ๋ ฌ๋์ง ์์ ์ํ๋ก ๋ฐํ๋จ)
List<Dish> slicedMenu3 = specialMenu.stream()
.filter(dish -> dish.getCalories() > 300)
.limit(3)
.collect(toList());
-
skip(n)
: ์ฒ์ n๊ฐ ์์๋ฅผ ์ ์ธํ ์คํธ๋ฆผ์ ๋ฐํ
List<Dish> slicedMenu4 = specialMenu.stream()
.filter(dish -> dish.getCalories() > 300)
.skip(2)
.collect(toList());
- ์คํธ๋ฆผ ๊ฐ ์์์ ํจ์ ์ ์ฉํ๊ธฐ
- ๋ณํ์ ๊ฐ๊น์ด ๋งคํ : ์คํธ๋ฆผ์ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋ map ๋ฉ์๋๋ฅผ ์ง์ํ๋ค. ์ธ์๋ก ์ ๊ณต๋ ํจ์๋ ๊ฐ ์์์ ์ ์ฉ๋๋ฉฐ ํจ์๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ๊ฐ ์๋ก์ด ์์๋ก ๋งคํ๋๋ค.
// map ๋ฉ์๋์ ์ถ๋ ฅ ์คํธ๋ฆผ์ Stream<String>
List<String> dishNames = menu.stream()
.map(Dish::getName)
.collect(toList());
-
Arrays.stream
: ๋ฌธ์์ด์ ๋ฐ์ ์คํธ๋ฆผ์ ๋ง๋ ๋ค.
String[] arrayOfWords = {"Hello", "World"};
Stream<String> streamOfWords = Arrays.stream(arrayOfWords);
words.stream()
.map(word -> word.split("");
.map(Arrays::stream)
.distinct()
.collect(toList();
-
flapMap
: ๊ฐ ๋ฐฐ์ด์ ์คํธ๋ฆผ์ ์ฝํ ์ธ ๋ก ๋งคํํ์ฌ ํ๋์ ํ๋ฉดํ๋ ์คํธ๋ฆผ์ ๋ฐํ
List<String> uniqueCharacters = words.stream()
.map(word -> word.split("");
.flatMap(Arrays::stream)
.distinct()
.collect(toList());
-
anyMatch
: ํ๋ ๋์ผ์ดํธ๊ฐ ์ฃผ์ด์ง ์คํธ๋ฆผ์์ ์ ์ด๋ ํ ์์์ ์ผ์นํ๋์ง ํ์ธ. ์ต์ข ์ฐ์ฐ
if(menu.stream().anyMatch(Dish::isVegetarian)
System.out.println("The menu is (somewhat) vegetarian friendly!!");
-
allMatch
: ์คํธ๋ฆผ์ ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง ํ๋ ๋์ผ์ดํธ์ ์ผ์นํ๋์ง ๊ฒ์ฌ
boolean isHealthy = menu.stream()
.allMatch(dish -> dish.getCalories() < 1000);
-
noneMatch
: ์ฃผ์ด์ง ํ๋ ๋์ผ์ดํธ์ ์ผ์นํ๋ ์์๊ฐ ์๋์ง ํ์ธ
boolean isHealthy = menu.stream()
.noneMatch(dish -> dish.getCalories() >= 1000);
-
์ผํธ์ํท : ์ ์ฒด ์คํธ๋ฆผ์ ์ฒ๋ฆฌํ์ง ์์๋๋ผ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๊ฒ
- &&, ||,
allMatch
,noneMatch
,findFirst
,findAny
...
- &&, ||,
-
findAny
: ํ์ฌ ์คํธ๋ฆผ์์ ์์์ ์์๋ฅผ ๋ฐํ. ๋ค๋ฅธ ์คํธ๋ฆผ ์ฐ์ฐ๊ณผ ์ฐ๊ฒฐํด์ ์ฌ์ฉํ ์ ์๋ค- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๋ด๋ถ์ ์ผ๋ก ๋จ์ผ ๊ณผ์ ์ผ๋ก ์คํํ ์ ์๋๋ก ์ต์ ํ๋๋ค
Optional<Dish> dish = menu.stream()
.filter(Dish::isVegetarian)
.findAny();
-
findFirst
: ํ์ฌ ์คํธ๋ฆผ์์ (๋ ผ๋ฆฌ์ ์ธ ์์ดํ ์์ ์ค)์ฒซ๋ฒ์งธ ์์๋ฅผ ๋ฐํ.
List<Integer> someNumbers = Arrays.asList(1,2,3,4,5);
Optional<Integer> firstSquareDivisibleByThree
= someNumbers.stream()
.map(n -> n*n)
.filter(n -> n%3 == 0)
.findFirst();
-
Optional<T>
(java.util.Optional)- ๊ฐ์ ์กด์ฌ๋ ๋ถ์ฌ ์ฌ๋ถ๋ฅผ ํํํ๋ ์ปจํ ์ด๋ ํด๋์ค
-
findAny
๋ฑ์ ๋ฉ์๋ ์ฌ์ฉ์ ์๋ฌด ์์๋ ๋ฐํํ์ง ์์ ์ ์๋ค. ์ด๋ฐ ๊ฒฝ์ฐ๋ค์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ๊ฐ์ ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณต-
isPresent()
: ๊ฐ์ ํฌํจํ๋ true, ํฌํจํ์ง ์์ผ๋ฉด false -
isPresent(Consumer<T> block)
: ๊ฐ์ด ์์ผ๋ฉด ์ฃผ์ด์ง block ์คํ -
T get()
: ๊ฐ์ด ์กด์ฌํ๋ฉด ๊ฐ์ ๋ฐํ, ๊ฐ์ด ์์ผ๋ฉด NoSuchElementException -
T orElse(T other)
: ๊ฐ์ด ์์ผ๋ฉด ๊ฐ์ ๋ฐํ, ๊ฐ์ด ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ์ ๋ฐํ
-
menu.stream()
.filter(Dish::isVegetarian)
.findAny() <- Optional<Dish> ๋ฐํ
.ifPresent(dish -> System.out.println(dish.getName());
- ๋ฆฌ๋์ฑ ์ฐ์ฐ : ๋ชจ๋ ์คํธ๋ฆผ ์์๋ฅผ ์ฒ๋ฆฌํด์ ๊ฐ์ผ๋ก ์ฒ๋ฆฌํ๋ ์ง์
-
reduce
- ์ด๊น๊ฐ
- ๋ ์์๋ฅผ ์กฐํฉํด์ ์๋ก์ด ๊ฐ์ ๋ง๋๋ BinaryOperator
int product = numbers.stream().reduce(1, (a, b) -> a*b);
- ์๋ฐ8์์๋ Integer ํด๋์ค์ ๋ ์ซ์๋ฅผ ๋ํ๋ ์ ์
sum
๋ฉ์๋ ์ ๊ณต
int sum = numbers.stream().reduce(0, Integer::sum);
- ์คํธ๋ฆผ ์ฐ์ฐ : ์ํ ์์๊ณผ ์ํ ์์
-
map
,filter
๋ฑ์ ์ ๋ ฅ ์คํธ๋ฆผ์์ ๊ฐ ์์๋ฅผ ๋ฐ์ 0 ๋๋ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅ ์คํธ๋ฆผ์ผ๋ก ๋ณด๋ธ๋ค. ์ํ๊ฐ ์๋, ๋ด๋ถ ์ํ๋ฅผ ๊ฐ์ง ์๋ ์ฐ์ฐ์ด๋ค. -
reduce
,sum
,max
๊ฐ์ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋์ ํ ๋ด๋ถ ์ํ๊ฐ ํ์ํ๋ค. ์คํธ๋ฆผ์์ ์ฒ๋ฆฌํ๋ ์์ ์์ ๊ด๊ณ์์ด ๋ด๋ถ ์ํ์ ํฌ๊ธฐ๋ ํ์ ๋์ด์๋ค.
-
- ๊ธฐ๋ณธํ ํนํ ์คํธ๋ฆผ : ์คํธ๋ฆผ api ์ซ์ ์คํธ๋ฆผ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋๋ก ํ๋ ์คํธ๋ฆผ
- ์ซ์ ์คํธ๋ฆผ์ผ๋ก ๋งคํ(IntStream, DoubleStream, LongStream)
-
reduce
์ ๊ฐ์ ์คํธ๋ฆผ์ ์จ์ด์๋ ๋ฐ์ฑ ๋น์ฉ์ ํผํ ์ ์๋๋ก ์ ๊ณต. ๋ฐ์ฑ ๊ณผ์ ์์ ์ผ์ด๋๋ ํจ์จ์ฑ๊ณผ ๊ด๋ จ ์์ผ๋ฉฐ ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ ์์ -
mapToInt
,mapToDouble
,mapToLong
-
max
,min
,average
๋ฑ ๋ค์ํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ ์ง์
-
- ๊ฐ์ฒด ์คํธ๋ฆผ์ผ๋ก ๋ณต์
-
boxed
๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ํนํ ์คํธ๋ฆผ์ ์ผ๋ฐ ์คํธ๋ฆผ์ผ๋ก ๋ณํ ํ ์ ์๋ค
-
- ์ซ์ ์คํธ๋ฆผ์ผ๋ก ๋งคํ(IntStream, DoubleStream, LongStream)
int clories = menu.stream() <- Stream<Dish> ๋ฐํ
.mapToInt(Dish::getcalories) <- IntStream ๋ฐํ
.sum();
IntStream intStream = menu.stream().mapToInt(Dish::getCalories); <- ์คํธ๋ฆผ์ ์ซ์ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
Stream<Integer> stream = intStream.boxed(); <- ์ซ์ ์คํธ๋ฆผ์ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
- ๊ธฐ๋ณธ๊ฐ : OptionalInt
- ์คํธ๋ฆผ์ ์์๊ฐ ์์ ๋์ ์ต๋๊ฐ์ด 0์ธ ์ํฉ์ ๋ํ ๊ตฌ๋ณ ๋ฐฉ๋ฒ
:
OptionalInt
,OptionalDouble
,OptinalLong
-
orElse
: ๊ฐ์ด ์์ ๋ ๊ธฐ๋ณธ ์ต๋๊ฐ์ ๋ช ์์ ์ผ๋ก ์ค์
- ์คํธ๋ฆผ์ ์์๊ฐ ์์ ๋์ ์ต๋๊ฐ์ด 0์ธ ์ํฉ์ ๋ํ ๊ตฌ๋ณ ๋ฐฉ๋ฒ
:
OptionalInt maxCalories = menu.stream()
.mapToInt(Dish::geCalories)
.max();
int max = maxCalories.orElse(1);
- ์ซ์ ๋ฒ์
-
range
: ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์์๊ฐ, ๋ ๋ฒ์งธ ์ธ์๋ก ์ข ๋ฃ๊ฐ. ์์๊ฐ, ์ข ๋ฃ๊ฐ์ ๊ฒฐ๊ณผ์ ํฌํจ๋์ง ์์ -
rangeClosed
: ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์์๊ฐ, ๋ ๋ฒ์งธ ์ธ์๋ก ์ข ๋ฃ๊ฐ. ์์๊ฐ, ์ข ๋ฃ๊ฐ์ ๊ฒฐ๊ณผ์ ํฌํจ๋จ
-
IntStream evenNumbers = IntStream.rangeClosed(1, 100)
.filter(n -> n%2 == 0);
System.out.println(evenNumbers.count());
- ๊ฐ์ผ๋ก ์คํธ๋ฆผ ๋ง๋ค๊ธฐ
-
Stream.of
: ์์์ ์๋ฅผ ์ธ์๋ก ๋ฐ๋ ์ ์ ๋ฉ์๋ -
Stream.empty
: ์คํธ๋ฆผ์ ๋น์ฐ๋ ๋ฉ์๋
-
// ์คํธ๋ฆผ์ ๋ชจ๋ ๋ฌธ์์ด์ ๋๋ฌธ์๋ก ๋ณํํ ํ ๋ฌธ์์ด์ ํ๋์ฉ ์ถ๋ ฅ
Stream<String> stream = Stream.of("Modern", "Java", "In", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);
// ์คํธ๋ฆผ์ ๋น์
Stream<String> emptyStream = Stream.empty();
- null์ด ๋ ์ ์๋ ๊ฐ์ฒด๋ก ์คํธ๋ฆผ ๋ง๋ค๊ธฐ
-
System.getProperty
: ์ ๊ณต๋ ํค์ ๋์ํ๋ ์์ฑ์ด ์์ผ๋ฉด null์ ๋ฐํ -
Stream.ofNullable
: null์ ๋ช ์์ ์ผ๋ก ํ์ธ
-
String homeValue = System.getProperty("home");
Stream<String> homeValueStream = homeValue == null ? Stream.empty() : Stream.of(value);
Stream<String> homeValueStream = Stream.ofNullable(System.getProperty("home"));
Stream<String> values = Stream.of("config", "home", "user")
.flatMap(key -> Stream.ofNullable(System.getProperty(key)));
- ๋ฐฐ์ด๋ก ์คํธ๋ฆผ ๋ง๋ค๊ธฐ
-
Arrays.stream
: ๋ฐฐ์ด์ ์ธ์๋ก ๋ฐ๋ ์ ์ ๋ฉ์๋. int๋ก ์ด๋ฃจ์ด์ง ๋ฐฐ์ด์ IntStream์ผ๋ก ๋ณํ
-
int[] numbers = {2,3,5,7,11,13};
int sum = Arrays.stream(numbers).sum();
- ํ์ผ๋ก ์คํธ๋ฆผ ๋ง๋ค๊ธฐ
-
Files.lines
: ์ฃผ์ด์ง ํ์ผ์ ํ ์คํธ๋ฆผ์ ๋ฌธ์์ด๋ก ๋ฐํ - Stream ์ธํฐํ์ด์ค๋ AutoCloseable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ฌ try ๋ธ๋ก ๋ด์ ์์์ด ์๋์ผ๋ก ๊ด๋ฆฌ๋๋ค
-
long uniqueWords = 0;
try(Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct()
.count();
} catch(IOException e) {
}
- ํจ์๋ก ๋ฌดํ ์คํธ๋ฆผ ๋ง๋ค๊ธฐ
-
Stream.iterate
: ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ง ์๋ ๋ฌดํ ์คํธ๋ฆผ(์ธ๋ฐ์ด๋ ์คํธ๋ฆผ) ์์ฑ. ์๋ฐ9์์๋ ํ๋ ๋์ผ์ดํธ๋ฅผ ์ง์ -
Stream.generate
: ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ง ์๋ ๋ฌดํ ์คํธ๋ฆผ(์ธ๋ฐ์ด๋ ์คํธ๋ฆผ) ์์ฑ. Supplier๋ฅผ ์ธ์๋ก ๋ฐ์์ ์๋ก์ด ๊ฐ์ ์์ฐ. - ๋ฌดํ ์คํธ๋ฆผ์ ์์๋ ๋ฌดํ์ ์ผ๋ก ๊ณ์ฐ์ด ๋ฐ๋ณต๋๋ฏ๋ก ์ ๋ ฌํ๊ฑฐ๋ ๋ฆฌ๋์คํ ์ ์๋ค.
-
Stream.iterate(0, n -> n+2)
.limit(10)
.forEach(System.out::println);
IntStream.iterate(0, n -> n < 100, n -> n+4)
.forEach(System.out::println);
IntStream.iterate(0, n -> n+4)
.filter(n -> n < 100) // ๋ถ๊ฐ๋ฅ!
.forEach(System.out::println);
IntStream.iterate(0, n -> n+4)
.takeWhile(n -> n < 100)
.forEach(System.out::println);
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);
// IntStream์ generate ๋ฉ์๋๋ Supplier<T> ๋์ ์ IntSupplier๋ฅผ ์ธ์๋ก ๋ฐ์
IntStream ones = IntStream.generate(() -> 1);
IntStream twos = IntStream.generate(new IntSupplier(){
public int getAsInt(){
return 2;
}
});
IntSupplier fid = new IntSupplier() {
private int previous = 0;
private int current = 1;
public int getAsInt() {
int oldPrevious = this.previous;
int nextValue = this.previous + this.current;
this.previous = this.current;
this.current = nextValue;
return oldPrevious;
}
};
IntStream.generate(fib)
.limit(10)
.forEach(System.out::println());