์คํธ๋ฆผ ํ์ฉ
๋ช ์์ ๋ฐ๋ณต ๋์ filter์ collect ์ฐ์ฐ์ ์ง์ํ๋ ์คํธ๋ฆผ API๋ฅผ ์ด์ฉํด์ ๋ฐ์ดํฐ ์ปฌ๋ ์ ๋ฐ๋ณต์ ๋ด๋ถ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
@Test
void streamSample() {
List<String> nameList = new ArrayList<>();
nameList.add("๋ญ์ค");
nameList.add("๋ฃฐ๋ฃจ");
nameList.add("์ ์ฌ");
nameList.add("ํธ๋ฆฐ๋ค๋ฏธ์ด");
// ์ธ๋ถ ๋ฐ๋ณต
List<String> longNameList = new ArrayList<>();
for (String s : nameList) {
if(s.length() > 5) {
longNameList.add(s);
}
}
// ๋ด๋ถ ๋ฐ๋ณต
List<String> longNameStreamList = nameList.stream()
.filter(s -> s.length() >5)
.collect(Collectors.toList());
}
์คํธ๋ฆผ API๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ๊ด๋ฆฌํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ ํธํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
๋ค์ํ ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๊ณ , ๋ณ๋ ฌ๋ก ์คํํ ์ง ์ฌ๋ถ๋ ๊ฒฐ์ ํด์ค๋ค.
์์ฐจ์ ์ธ ๋ฐ๋ณต์ ๋จ์ผ ์ค๋ ๋๋ก ๊ตฌํํ๋ ์ธ๋ถ ๋ฐ๋ณต์ ์ด๋ฅผ ํ ์ ์์ผ์ .
ํํฐ๋ง
ํํฐ๋ง์ ์คํธ๋ฆผ์ ์์๋ฅผ ์ ํํ๋ ๋ฐฉ๋ฒ์ธ Predicate ํํฐ๋ง ๋ฐฉ๋ฒ๊ณผ ๊ณ ์ ์์๋ง ํํฐ๋ง ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
Predicate๋ฅผ ์ด์ฉํ ํํฐ๋ง
// Dish ํด๋์ค์ Predicate ๋ฉ์๋
public boolean isVegetarian() {
return vegetarian;
}
@Test
@DisplayName("Predicate filtering")
void predicateFilter() {
List<Dish> vegetarianMenu = menuList.stream()
.filter(Dish::isVegetarian) // Predicate
.collect(Collectors.toList());
}
์คํธ๋ฆผ ์ธํฐํ์ด์ค์์ ์ง์ํ๋ filter ๋ฉ์๋์์ Predicate ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์์ Predicate ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ ์์๋ฅผ ํฌํจํ๋ ์คํธ๋ฆผ์ ๋ฐํํ๋ค.
๊ณ ์ ์์ ํํฐ๋ง
์คํธ๋ฆผ์ ๊ณ ์ ์์๋ก ์ด๋ฃจ์ด์ง ์คํธ๋ฆผ์ ๋ฐํํ๋ distinct ๋ฉ์๋๋ ์ง์ํ๋ค.
์คํธ๋ฆผ์์ ๊ฐ์ฒด๋ค์ ๊ณ ์ ์ฑ์ ํ๋จํ ๋, ํด๋น ๊ฐ์ฒด๋ค์ hashCode์ equals ๋ฉ์๋๊ฐ ํธ์ถํ๋ค.
hashCode์ equals ๋ฉ์๋
Java ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ๊ฐ์ฒด์ ๊ณ ์ ์ฑ์ ๊ฒฐ์ ํ ๋, hashCode
๋ฉ์๋์ equals
๋ฉ์๋๊ฐ ์ฌ์ฉ๋๋ค
- hashCode ๋ฉ์๋:
hashCode
๋ฉ์๋๋ ๊ฐ์ฒด์ ํด์ ์ฝ๋๋ฅผ ๋ฐํํฉ๋๋ค. ํด์ ์ฝ๋๋ ๊ฐ์ฒด๋ฅผ ๋ํ๋ด๋ ์ ์ ๊ฐ์ด๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ํด ์๋ก ๋ค๋ฅธ ํด์ ์ฝ๋๊ฐ ๋ฐํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ๊ฐ์ ํด์ ์ฝ๋๋ฅผ ๊ฐ์ง ์๋ ์์ต๋๋ค. ๋ฐ๋ผ์ ํด์ ์ฝ๋๋ ๊ฐ์ฒด๋ฅผ ์๋ณํ๋ ๋ฐ ์์ ํ ์ ๋ขฐํ ์ ์๋ ์๋จ์ ์๋๋๋ค.
- equals ๋ฉ์๋:
equals
๋ฉ์๋๋ ๋ ๊ฐ์ฒด๊ฐ ๋๋ฑํ์ง ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค. ์ฆ, ๋ ๊ฐ์ฒด๊ฐ ์๋ก ๊ฐ์ ๋ด์ฉ์ ๊ฐ์ง๊ณ ์๋์ง๋ฅผ ํ๋จํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๋ฉ์๋๋ฅผ ์ ์ ํ ์ฌ์ ์ํ์ฌ ๊ฐ์ฒด ๊ฐ์ ๋ด์ฉ์ ์ธ ๋น๊ต๋ฅผ ์ํํ ์ ์๋๋ก ํด์ผ ํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ด ๋ ๋ฉ์๋๋ ํจ๊ป ์ฌ์ฉ๋๋ฉฐ, ๊ฐ์ฒด๊ฐ ๊ฐ์์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
์๋ฅผ ๋ค์ด, Java์ ์ปฌ๋ ์
ํ๋ ์์ํฌ์์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋ ๊ฒ์ํ ๋, hashCode
์ equals
๊ฐ ์ ๋๋ก ๊ตฌํ๋์ง ์์ผ๋ฉด ์ํ๋ ๋์์ ์ป์ ์ ์์ ์ ์์ต๋๋ค.
์๋ฐ์์๋ hashCode
์ equals
๋ฅผ ์ ์ ํ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ฐ์ฒด์ ๋๋ฑ์ฑ(equality)์ ์ ์ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ง์ฝ ์ด๋ฅผ ์ ๋๋ก ์ฒ๋ฆฌํ์ง ์์ผ๋ฉด ๊ฐ์ฒด์ ๋๋ฑ์ฑ์ ๊ฒ์ฌํ๋๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์๋ฌดํผ.. distinct ๋จ์ด ๋ป์ฒ๋ผ, ๋ฐ์ดํฐ์ ์์์์ ์ค๋ณต์ ํํฐ๋ง ํฉ๋๋ค.
์คํธ๋ฆผ ์ฌ๋ผ์ด์ฑ
Predicate๋ฅผ ์ด์ฉํ ์ฌ๋ผ์ด์ฑ
์๋ฐ 9์๋ ์คํธ๋ฆผ์ ์์๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ ํํ ์ ์๋๋ก ํ๋ ๋ฉ์๋์ธ, takeWhile๊ณผ dropWhile์ด ์๋ค๊ณ ํ๋ค.
takeWhile
@Test
@DisplayName("takeWhile")
void takeWhileTest() {
// 100 ์นผ๋ก๋ฆฌ ์ดํ ์๋ฆฌ ์ ํํ๊ธฐ ์ํด filter() ์ฌ์ฉ
List<Dish> filteredMenu = menuList.stream()
.filter(dish -> dish.getCalories() < 100)
.collect(Collectors.toList());
}
๋ง์ฝ 100 ์นผ๋ก๋ฆฌ ์ดํ์ธ ์๋ฆฌ๋ฅผ ์ ํํ๋ ค๋ฉด ์์ ๊ฐ์ด filter ํจ์๋ฅผ ์จ์ ํ ์ ์๋ค.
filter ์ฐ์ฐ์ ์ด์ฉํ๋ฉด ์ ์ฒด ์คํธ๋ฆผ์ ๋ฐ๋ณตํ๋ฉด์ ๊ฐ ์์์ Predicate๋ฅผ ์ ์ฉํ๊ฒ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์นผ๋ก๋ฆฌ ์์ผ๋ก ์ด๋ฏธ ์ ๋ ฌ์ด ๋์ด์์.
์ด๋ฏธ ๋ฆฌ์คํธ๊ฐ ์นผ๋ก๋ฆฌ ์์ผ๋ก ์ ๋ ฌ๋์ด์๋ค๋ฉด ๋๊ฐ์ Predicate๋ฅผ ๋ฐ๋ณตํ ํ์๋ ์๋ ๊ฒ์.
๋ง์ฝ ์คํธ๋ฆผ์ ๋ฐฑ๋ง๊ฐ์ ์์๊ฐ ์๋ค๋ฉด ์ฑ๋ฅ์ ์ฐจ์ด๊ฐ ๋ ์ ๋ฐ์ ์์.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ๊ฒ takeWhile์ด๋ ๋ง์.
.stream()
.takeWhile(dish -> dish.getCaloried() < 100)
dropWhile
๊ทธ๋ฌ๋ฉด ๋ง์ฝ 100 ์นผ๋ก๋ฆฌ๋ณด๋ค ํฐ ์๋ฆฌ๋ฅผ ํ์ํ๋ ค๋ฉด? dropWhile์ ์ด์ฉํด์ ํ ์ ์๋ค.
.stream()
.dropWhile(dish -> dish.getCalories() < 100)
takeWhile๊ณผ ์ ๋ฐ๋์ ์์ ์ ์ํํจ. Predicate๊ฐ ์ฒ์์ผ๋ก ๊ฑฐ์ง์ด๋๋ ์ง์ ๊น์ง ๋ฐ๊ฒฌ๋๋ ์์๋ค์ ๋ฒ๋ ค์ค๋ค.
๋ฌดํํ ๋จ์ ์์๋ฅผ ๊ฐ์ง ๋ฌดํ ์คํธ๋ฆผ์์๋ ๋์ํ๋ค๊ณ ํจ.
์คํธ๋ฆผ ์ถ์
๊ฐ์ ํํฐ๋ง ํ๋ค๋ฉด, ์์์ ๊ฐ์์๋ ์ ํ์ ๊ฑธ ์ ์๋ค. limit(n) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์คํธ๋ฆผ์ด ์ ๋ ฌ๋์ด์๋ค๋ฉด ์ต๋ ์์ n๊ฐ๋ฅผ ๋ฐํํด์ค๋ค.
List<Dish> limit3Menu = menuList.stream()
.filter(dish -> dish.getCalories() < 100)
.limit(2)
.collect(Collectors.toList());
์คํธ๋ฆผ ์์ ๊ฑด๋๋ฐ๊ธฐ
limit๋ ๊ทธ๋ ๊ณ skip๋ filter ๊ฐ์ ๋ค๋ฅธ ์ฐ์ฐ๊ณผ ์ํธ ๋ณด์์ ์ธ ์ฐ์ฐ์ ์ํํด์ค๋ค.
List<Dish> skip2Menu = menuList.stream()
.filter(dish -> dish.getCalories() < 100)
.skip(2)
.collect(Collectors.toList());
Mapping
์คํธ๋ฆผ์์๋ ํน์ ๋ฐ์ดํฐ๋ฅผ ์ ํํ๋ ์์ ์ ์ํํ๋ ์ฐ์ฐ์ธ map๊ณผ flatMap์ ์ง์ํ๋ค.
์คํธ๋ฆผ์ ๊ฐ ์์์ ํจ์ ์ ์ฉํ๊ธฐ
map ๋ฉ์๋๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค. ์ธ์๋ก ์ ๊ณต๋ ํจ์๋ ๊ฐ ์์์ ์ ์ฉ๋๊ณ ์ ์ฉํ ๊ฒฐ๊ณผ๊ฐ ์๋ก์ด ์์๋ก ๋งตํ๋๋ค.
๊ธฐ์กด์ ๊ฐ์ ์๋ก์ด ๋ฒ์ ์ผ๋ก ๋ง๋๋ ๊ฐ๋ ์ด๋ค.
@Test
@DisplayName("Mapping")
void mappingTest() {
List<String> dishNameList = menuList.stream()
.map(Dish::getName)
.collect(Collectors.toList());
}
์๋ฆฌ์ ์ด๋ฆ์ ๊ฐ์ ธ์ค๋ getName์ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ์ ์์ฑํ์๊ธฐ ๋๋ฌธ์, ์ถ๋ ฅ ์คํธ๋ฆผ์ Stream ํ์์ด๋ค.
List<Integer> dishNameLengthList = dishNameList.stream()
.map(String::length)
.collect(Collectors.toList());
์๋ฆฌ์ ์ด๋ฆ์ ๊ฐ์ ธ์ค๋ ๋ฆฌ์คํธ๋ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ค.
์๋ฆฌ์ ์ด๋ฆ์ ์ธ์๋ก ๋ฐ์์, ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ String::length๋ฅผ map ๋ฉ์๋์ ์ ๋ฌํ๋ฉด ํด๊ฒฐํ ์ ์๋ค.
List<Integer> dishNameLengthList = menuList.stream()
.map(Dish::getName)
.map(String::length)
.collect(Collectors.toList());
์๋ฆฌ ๋ฆฌ์คํธ์์ ํ๋ฒ์ ์๋ฆฌ์ ์ด๋ฆ์ ๊ธธ์ด ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ ธ์ฌ ์๋ ์๋ค.
์ด๋ฅผ Chaining์ด๋ผ๊ณ ํ๋ค.
์คํธ๋ฆผ ํ๋ฉดํ
๋ฆฌ์คํธ๋ก ์ป์ด์จ ๋ฌธ์์ด์ ์ชผ๊ฐ์ ๊ณ ์ ๋ฌธ์๋ก ์ด๋ฃจ์ด์ง ๋ฆฌ์คํธ๊ฐ ๋ฐํ๋๋๋ก ํ ์ ์๋ค.
@Test
@DisplayName("์ค๋ณต๋ ๋ฌธ์๊ฐ ์ ๊ฑฐ๋ ๋ฌธ์์ด ๋ฆฌ์คํธ")
void splitWordsTest() {
List<String> words = Arrays.asList("apple", "peach", "banana");
List<String> wordList = words.stream()
.map(word -> word.split(""))
.distinct()
.collect(Collectors.toList());
System.out.println(wordList);
}
Stream ํ์์ ๊ฐ๋ ์คํธ๋ฆผ์ ๊ธฐ๋ํ์ง๋ง.. ์์ฝ๊ฒ๋ ์๋์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
ํ์
๋ณ์์ ์ธ์คํด์ค๊ฐ ์์ผ๋ฏ๋ก String[]์ด(๊ฐ) String์(๋ฅผ) ์ค์ํฉ๋๋ค ์ถ๋ก ๋ณ์ T์ ํธํ๋์ง ์๋ ๋ฐ์ด๋๊ฐ ์์ต๋๋ค. equality constraints: String lower bounds: String[]
์์ ๊ฐ์ด ํ์์ ๊ฒฝ์ฐ์๋ Stream<String[]> ํ์์ผ๋ก ๋ฐํ๋๋ ๊ฒ์ด๋ค.
split์ด ๋ฐฐ์ด์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค.
@NotNull
@Contract(pure = true)
public String[] split(@NotNull String regex, int limit )
ํ์ง๋ง Stream์ ์ํ๋ค๊ตฌ...! ์ด๋ด ๋ ์ฌ์ฉํ๋ ๊ฒ์ด flatMap ๋ฉ์๋์ด๋ค.
๋ง์ฝ ์์ ์์ ๋ฅผ Stream<String[]>๋ก ๋ณ๊ฒฝํ๋ฉด ์๋์ ๊ฐ์ด ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋๋ค.
[[Ljava.lang.String;@7fb95505, [Ljava.lang.String;@58be6e8, [Ljava.lang.String;@7331196b]
map๊ณผ Arrays.stream
flatMap์ ์ฌ์ฉํ๊ธฐ ์ ์, ๋ฐฐ์ด ์คํธ๋ฆผ ๋์ ์ ๋ฌธ์์ด ์คํธ๋ฆผ์ ๋ด๋ณด์.
/**
String[] words = {"apple", "peach"};
Stream<String> stream = Arrays.stream(words);
*/
List<Stream<String>> wordList = words.stream()
.map(word -> word.split(""))
.map(Arrays::stream)
.distinct()
.collect(Collectors.toList());
Arrays::stream์ ์ฌ์ฉํด์ ๋ฌธ์์ด์ ๋ฐ์ ์คํธ๋ฆผ์ ๋ฐ์ ์๋ ์์ง๋ง, ์คํธ๋ฆผ ๋ฆฌ์คํธ๊ฐ ๋ง๋ค์ด์ก๊ธฐ ๋๋ฌธ์ ์๋ ๋ชฉํ์ธ Stream์ ๋ง๋ค์ด์ง์ง ์์๋ค.
๊ฐ ๋จ์ด๋ฅผ ๊ฐ๋ณ ๋ฌธ์์ด๋ก ์ด๋ฃจ์ด์ง ๋ฐฐ์ด๋ก ๋ง๋ ๋ค์์, ๊ฐ ๋ฐฐ์ด์ ๋ณ๋์ ์คํธ๋ฆผ์ผ๋ก ๋ง๋ค์ด์ผํ๋ค.
List<String> wordStrings = words.stream()
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
//[a, p, l, e, c, h, b, n]
์ด๋ ๊ฒ ๋ง์ด๋ค.
flatMap์ ๊ฐ ๋ฐฐ์ด์ ์คํธ๋ฆผ์ด ์๋๋ผ, ์คํธ๋ฆผ์ ์ฝํ ์ธ ๋ก ๋งตํํด์ค๋ค.
์ด๋ฆ์ฒ๋ผ flatํ๊ฒ~ ํ๋ฉดํ๋ ์คํธ๋ฆผ์ ๋ฐํํด์ค๋ค.
์ฆ, flatMap ๋ฉ์๋๋ ์คํธ๋ฆผ์ ๊ฐ ๊ฐ์ ๋ค๋ฅธ ์คํธ๋ฆผ์ผ๋ก ์์์ ๋ฐ๊พธ๊ณ , ๋ชจ๋ ์คํธ๋ฆผ์ ํ๋์ ์คํธ๋ฆผ์ผ๋ก ์ฐ๊ฒฐ๊น์ง ํด์ฃผ๋ ๊ฒ์ด๋ค...
์์
flatMap ์์ ๊ฐ ๋ง์์ ๋ค์ด์ ์ถ๊ฐ๋ก ์์ฑํด๋ณธ๋ค.
๋ง์ฝ์ ๋ ๊ฐ์ ์ซ์ ๋ฆฌ์คํธ๊ฐ ์๋๋ฐ, ๋ชจ๋ ์ซ์ ์์ ๋ฆฌ์คํธ๋ฅผ ๊ตฌํ๋๋ฐ ๊ทธ ์ค ์ซ์ ์์ ํฉ์ด 3์ผ๋ก ๋๋์ด ๋จ์ด์ง๋ ์ซ์ ์์ ๊ตฌํ๊ณ ์ถ๋ค๋ฉด?
์ด๋ฅผ ๊ตฌ๋ฅ๋ค๋ฆฌ c์ธ์ด๋ก ๋ง๋ค๋ฉด ์ด๋ ๊ฒ ํ ์ ์๋ค.
#include <stdio.h>
int main() {
int numberList1[] = {1, 2, 3};
int numberList2[] = {3, 4};
int pairs[6][2];
int count = 0;
for (int i = 0; i < sizeof(numberList1) / sizeof(numberList1[0]); i++) {
for (int j = 0; j < sizeof(numberList2) / sizeof(numberList2[0]); j++) {
if ((numberList1[i] + numberList2[j]) % 3 == 0) {
pairs[count][0] = numberList1[i];
pairs[count][1] = numberList2[j];
count++;
}
}
}
// Displaying the pairs
for (int i = 0; i < count; i++) {
printf("[%d, %d]\n", pairs[i][0], pairs[i][1]);
}
return 0;
}
๋๋ฌด ์ซ์ ์ด์ค for๋ฌธ.. ๊ฐ๋ ์ฑ๋ ์ ์ข๊ณ ๋จ์ํ ์์ ์ด์ง๋ง i์ j๊ฐ ํท๊ฐ๋ฆด ์ ๋ฐ์ ์๋ ๊ทธ๋ฐ... (์ด๋ฆ์ ์ ์ ํ๋ฉด ๋์ง๋ง.. ๊ทธ์น๋ง..)
์ด๋ฅผ flatMap์ ์ฌ์ฉํ ์คํธ๋ฆผ์ ์ฌ์ฉํด์ ์์ฑํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
@Test
@DisplayName("์ซ์ ๋ฆฌ์คํธ์ ๋ชจ๋ ์ซ์์ ์์์ ํฉ์ด 3์ผ๋ก ๋๋์ด์ง๋ ์์ ")
void numberListTest() {
List<Integer> numberList1 = Arrays.asList(1,2,3);
List<Integer> numberList2 = Arrays.asList(3,4);
List<int[]> pairs = numberList1.stream()
.flatMap(i -> numberList2.stream()
.filter(j->(i+j) % 3 == 0 )
.map(j-> new int[] {i, j}))
.collect(Collectors.toList());
}
๊ฒ์๊ณผ ๋งค์นญ
์คํธ๋ฆผ์ ํน์ ์์ฑ์ด ๋ฐ์ดํฐ ์งํฉ์ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฒ์ํ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์๋ ์ฌ์ฉํ ์ ์๋ค.
allMatch, anyMatch, noneMatch, findFirst, findAny ๋ฑ์ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๊ฐ ์์.
๋ฉ์๋ ์ดํด๋ณด๊ธฐ
anyMatch: Predicate๊ฐ ์ ์ด๋ ํ ์์์ ์ผ์นํ๋์ง ํ์ธํ๊ธฐ
์ฃผ์ด์ง ์คํธ๋ฆผ์์ ์ ์ด๋ ํ ์์์ ์ผ์นํ๋์ง ํ์ธํ ๋ anyMatch ๋ฉ์๋๋ฅผ ์ธ ์ ์๋ค.
anyMatch๋ boolean์ ๋ฐํํ๊ธฐ ๋๋ฌธ์, if ๋ฌธ์ผ๋ก ๋น๊ตํ ๋ ์ฉ์ดํ๋ค.
@Test
@DisplayName("anyMatch๋ก ์ ์ด๋ ํ ์์์ ์ผ์นํ๋์ง ํ์ธํด๋ณด๊ธฐ")
void searchAndMatch() {
if(menuList.stream().anyMatch(Dish::isVegetarian)) {
System.out.println("The menu is (somewhat) vegetarian friendly");
}
}
flatMap ๊ณต๋ถํ ๋ ๊ตฌ๋ฅ๋ค๋ฆฌ C์ธ์ด๋ก ๋ฐ๊ฟ๋ณด๋ ์ฐธ ์ฌ๋ฐ๋๊ตฐ์...?
#include <stdio.h>
struct Dish {
int isVegetarian;
};
int anyMatch(struct Dish *menuList, int size) {
for (int i = 0; i < size; i++) {
if (menuList[i].isVegetarian) {
return 1; // True, at least one element is vegetarian
}
}
return 0; // False, no vegetarian element found
}
int main() {
struct Dish menuList[] = {
{1}, // Vegetarian
{0}, // Non-vegetarian
{1}, // Vegetarian
};
int menuSize = sizeof(menuList) / sizeof(menuList[0]);
if (anyMatch(menuList, menuSize)) {
printf("The menu is (somewhat) vegetarian friendly\n");
}
return 0;
}
allMatch: Prediacte๊ฐ ๋ชจ๋ ์์์ ์ผ์นํ๋์ง ๊ฒ์ฌํ๊ธฐ
anyMatch์ ๋ค๋ฅด๊ฒ ์คํธ๋ฆผ์ ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง Predicate์ ์ผ์นํ๋์ง ๊ฒ์ฌํ๋ค.
@Test
@DisplayName("allMatch๋ก ๋ชจ๋ ์์๊ฐ ์กฐ๊ฑด๊ณผ ์ผ์นํ๋์ง ๊ฒ์ฌํ๊ธฐ")
void allMatchTest() {
if(menuList.stream().allMatch(dish -> dish.getCalories() < 1000)) {
System.out.println("All menu is healthy");
}
}
noneMatch: ์ฃผ์ด์ง Predicate์ ์ผ์นํ๋ ์์๊ฐ ์๋์ง ํ์ธํ๊ธฐ
allMatch์ ๋ฐ๋์ด๋ค. ์๋ ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง Predicate์ ์ผ์นํ๋์ง ๊ฒ์ฌํ๋ค.
์์ allMatch๋ฅผ noneMatch๋ก ๋ฐ๊ฟ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ธ ์ ์๋ค.
@Test
@DisplayName("noneMatch๋ก ์กฐ๊ฑด๊ณผ ์ผ์นํ๋ ์์๊ฐ ์๋์ง ๊ฒ์ฌํ๊ธฐ")
void noneMatchTest() {
if(menuList.stream().noneMatch(dish -> dish.getCalories() >= 1000)) {
System.out.println("All menu is healthy");
}
}
short-circuit ๊ธฐ๋ฒ -> ๋ฐ๋ก ๋นผ๊ธฐ
anyMatch, allMatch, noneMatch ๋ฉ์๋๋ ์คํธ๋ฆผ ์ผํธ์ํท ๊ธฐ๋ฒ ์ฐ์ฐ์ ํ์ฉํ๋ค. (&&, ||)
์ผํธ์ํท(short-circuit)์ ์ฃผ๋ก ๋ ผ๋ฆฌ ์ฐ์ฐ์์ ๋ฐ์ํ๋ ๊ฐ๋ ์ด๋ค.
ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋ฉด ๋๋จธ์ง ์กฐ๊ฑด์ ํ๊ฐํ์ง ์๊ณ ์ ์ฒด ํํ์์ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ ๋งํ๋ค.
์ด๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ ผ๋ฆฌ ์ฐ์ฐ์์์ ์์ฃผ ๋ฐ์ํฉ๋๋ค.
๊ฐ์ฅ ํํ ์ผํธ์ํท ๊ธฐ๋ฒ์ ๋
ผ๋ฆฌ AND(&&
)์ OR(||
) ์ฐ์ฐ์์์ ๋ํ๋ฉ๋๋ค.
- ์ผํธ์ํท AND (
&&
): ๋ ผ๋ฆฌ AND์์๋ ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด์ด ๊ฑฐ์ง์ธ ๊ฒฝ์ฐ ๋๋จธ์ง ์กฐ๊ฑด์ ํ๊ฐํ์ง ์์ต๋๋ค. ์๋ํ๋ฉด ํ๋๋ผ๋ ๊ฑฐ์ง์ด๋ฉด ์ ์ฒด ํํ์์ ๊ฒฐ๊ณผ๋ ๊ฑฐ์ง์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.๋ง์ฝcondition1
์ด ๊ฑฐ์ง์ด๋ฉดcondition2
๋ ํ๊ฐ๋์ง ์์ต๋๋ค. if (condition1 && condition2) { // code }
- ์ผํธ์ํท OR (
||
): ๋ ผ๋ฆฌ OR์์๋ ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด์ด ์ฐธ์ธ ๊ฒฝ์ฐ ๋๋จธ์ง ์กฐ๊ฑด์ ํ๊ฐํ์ง ์์ต๋๋ค. ์๋ํ๋ฉด ํ๋๋ผ๋ ์ฐธ์ด๋ฉด ์ ์ฒด ํํ์์ ๊ฒฐ๊ณผ๋ ์ฐธ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.๋ง์ฝcondition1
์ด ์ฐธ์ด๋ฉดcondition2
๋ ํ๊ฐ๋์ง ์์ต๋๋ค. if (condition1 || condition2) { // code }
์ด๋ฌํ ์ผํธ์ํท ๊ธฐ๋ฒ์ ํ๋ก๊ทธ๋จ์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ์กฐ๊ฑด๋ง์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐ์ ํ ์ ์๋ ๊ฒฝ์ฐ ๋ถํ์ํ ์ถ๊ฐ ํ๊ฐ๋ฅผ ํ์ง ์๊ธฐ ๋๋ฌธ์ด์์ด~
๊ทธ๋์ allMatch
, anyMatch
, noneMatch
๋ฉ์๋๋ค๋ ๋ด๋ถ์ ์ผ๋ก ์ผํธ์ํท(short-circuit) ๊ธฐ๋ฒ์ ํ์ฉํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
allMatch
: ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ์ธํฉ๋๋ค. ๋ง์ฝ ์ด๋ค ์์๋ผ๋ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์์ผ๋ฉด ๋ค์ ์์๋ค์ ํ๊ฐํ์ง ์๊ณ ์ฆ์false
๋ฅผ ๋ฐํํฉ๋๋ค.boolean allMatch = stream.allMatch(element -> element > 0);
anyMatch
: ์ ์ด๋ ํ๋์ ์์๊ฐ ์ฃผ์ด์ง ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ์ธํฉ๋๋ค. ๋ง์ฝ ์ด๋ค ์์๋ผ๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด ๋ค์ ์์๋ค์ ํ๊ฐํ์ง ์๊ณ ์ฆ์true
๋ฅผ ๋ฐํํฉ๋๋ค.boolean anyMatch = stream.anyMatch(element -> element > 0);
noneMatch
: ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์๋์ง ํ์ธํฉ๋๋ค. ๋ง์ฝ ์ด๋ค ์์๋ผ๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด ๋ค์ ์์๋ค์ ํ๊ฐํ์ง ์๊ณ ์ฆ์false
๋ฅผ ๋ฐํํฉ๋๋ค.boolean noneMatch = stream.noneMatch(element -> element < 0);
allMatch
๋ ๋
ผ๋ฆฌ AND์ ์ ์ฌํ๊ฒ ๋์ํ๋ฉฐ, anyMatch
๋ ๋
ผ๋ฆฌ OR์ ์ ์ฌํ๊ฒ ๋์ํฉ๋๋ค. noneMatch
๋ ์กฐ๊ฑด์ ๋ถ์ ํ์ฌ allMatch
์ ๋น์ทํ ์ญํ ์ ํฉ๋๋ค.
๋ํ, ์ด ๋ฉ์๋๋ค์ ์ฌ์ฉํ ๋๋ ์ฃผ์ด์ง Predicate ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ชจ๋ ์์๋ฅผ ํ์ธํ์ง ์๊ณ ๋ ์ฆ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์, ์ผํธ์ํท ๊ธฐ๋ฒ์ด ์ ์ฉ๋์ด ํจ์จ์ ์ผ๋ก ๋์ํ๊ฒ ๋๋๊ฑฐ์์ด~
findAny: ํ์ฌ ์คํธ๋ฆผ์์ ์์์ ์์๋ฅผ ๋ฐํํ๊ธฐ
findAny ๋ฉ์๋๋ฅผ ๋ค๋ฅธ ์คํธ๋ฆผ ์ฐ์ฐ(filter ๊ฐ์)๊ณผ ์ฐ๊ฒฐํด์ ์ฌ์ฉํ ์ ์๋ค.
@Test
@DisplayName("findAny๋ก ์๋ฌด ์์๋ ๋ฐํํ๊ธฐ")
void findAnyTest() {
Optional<Dish> optionalDish = menuList.stream()
.filter(Dish::isVegetarian)
.findAny();
}
Optional (java.util.Optional)
์ต์ ๋์ ๊ฐ์ ์กด์ฌ๋ ๋ถ์ฌ ์ฌ๋ถ๋ฅผ ํํํ๋ ์ปจํ ์ด๋ ํด๋์ค์ด๋ค.
์๋ฐ 8 ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค๊ณ์๋ค์ null์ ๋ํด์๋ ๋ง์ ๊ณ ๋ฏผ์ ํ์๋๋ณด๋ค.
null์ ์ฝ๊ฒ ์๋ฌ๋ฅผ ์ผ์ผํฌ ์ ์๊ธฐ ๋๋ฌธ์, Optional๋ผ๋ ๊ฒ์ด ๋ง๋ค์ด์ก๋ค.
findFirst: ์ฒซ ๋ฒ์งธ ์์ ์ฐพ๊ธฐ
์ฐ์๋๋ ๋ฐ์ดํฐ๋ก ๋ง๋ ์คํธ๋ฆผ์์ ๋ ผ๋ฆฌ์ ์ธ ์์ดํ ์์๊ฐ ์ ํด์ ธ ์์ ๋, ์ฒซ ๋ฒ์งธ ์์๋ง ํ์ํ ๋๊ฐ ์์์ด?
๊ทธ๋ด ๋๋ findFirst๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
'๐ Java&Spring > ๋ชจ๋์๋ฐ์ธ์ก์ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[๋ชจ๋์๋ฐ์ธ์ก์ ] Stream ์คํธ๋ฆผ (6) | 2023.12.17 |
---|---|
[๋ชจ๋์๋ฐ์ธ์ก์ ] ๋๋ค (Lambda) (4) | 2023.12.03 |
[๋ชจ๋์๋ฐ์ธ์ก์ ] ๋์ ํ๋ผ๋ฏธํฐ(Behavior Parameter) (4) | 2023.11.19 |