-
Java8 - stream(์คํธ๋ฆผ), forEach(), map(), filter(), Method Reference(๋ฉ์๋ ์ฐธ์กฐ)๊ฐ๋ฐ/Java 2022. 4. 30. 00:20
stream์ด๋ผ๋ ์์ด ๋จ์ด๋ ๋ค์๊ณผ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ค.
1. ๊ฐ์ธ, ์๋ด
2. (์ก์ฒด๋ ๊ธฐ์ฒด์) ์ค๊ธฐ
3. (์ฌ๋์ด๋ ์ฐจ๋๋ค๋ก ๊ณ์ ์ด์ด์ง) ์ค
์์ ์๋ฏธ๋ก ๋ณด์์ ๋, "์ค์ค์ด ์ด์ด์ ธ ์๋" ์๋ฏธ๋ก ์ฌ์ฉ์ด ๋๋ค.
๐ก์๋ฐ์ ์คํธ๋ฆผ์ ์ธ์ ์ฌ์ฉํ ๊น?
์๋ฐ์ ์คํธ๋ฆผ์ "๋ญ๊ฐ ์ฐ์๋ ์ ๋ณด"๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฌ์ฉํ๋ค.
์๋ฐ์์๋ ๋ฐฐ์ด๊ณผ ์ปฌ๋ ์ ์ ์๊ฐํด๋ณผ ์ ์๊ฒ ๋ค. ํ์ง๋ง, ๋ฐฐ์ด์์๋ ์คํธ๋ฆผ์ ์ฌ์ฉํ ์ ์๋ค.
cf) ๊ทธ๋ ์ง๋ง, ๋ฐฐ์ด์ ์ปฌ๋ ์ ์ List๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์กด์ฌํ๋ค.
1) asList() ๋ฉ์๋๋ฅผ ์ด์ฉํ ๋ณํ
Integer[] values = {1, 3, 5}; List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));
2) Arrays.stream() ๋ฉ์๋๋ฅผ ์ด์ฉํ ๋ณํ
: ํด๋น ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด Stream๊ฐ์ฒด๋ฅผ ๋ฆฌํดํด์ค๋ค.
Integer[] values = {1, 3, 5}; //stream๊ฐ์ฒด๋ก ๋ณ๊ฒฝ, collect๋ ์ํ๋ ํ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฆฌํดํ๋ ๋ฉ์๋๋ค. List<Integer> list = Arrays.stream(values).collect(Collectors.toList());
๊ทธ๋ผ, ๋ณธ๊ฒฉ์ ์ผ๋ก ์คํธ๋ฆผ์ ๋ํด ์์๋ณด์.
๐ก์๋ฐ์ ์คํธ๋ฆผ์ ๊ตฌ์กฐ๋ ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ ธ ์์๊น? (์์์ผ๋ก ๊ตฌ๋ถ ์ค๋ช )
list.stream().filter(x-> x>10).count()
- ์คํธ๋ฆผ ์์ฑ : ์ปฌ๋ ์ ์ ๋ชฉ๋ก์ ์คํธ๋ฆผ ๊ฐ์ฒด๋ก ๋ณํํ๋ค. ์ฌ๊ธฐ์ ์คํธ๋ฆผ ๊ฐ์ฒด๋ java.util.stream ํจํค์ง์ Stream ์ธํฐํ์ด์ค๋ฅผ ๋งํ๋ค. ์ด stream() ๋ฉ์๋๋ ๋น์ฐํ Collection ์ธํฐํ์ด์ค์ ์ ์ธ๋์ด ์๋ค. stream()์ ์์ฐจ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ค. (10๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, 0~9๋ฒ์งธ ์ธ๋ฑ์ค๋ฅผ ํ๋์ฉ ์ฒ์๋ถํฐ ์ฒ๋ฆฌํ๋ค.)
- ์ค๊ฐ ์ฐ์ฐ : ์์ฑ๋ ์คํธ๋ฆผ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ์ค๊ฐ ์ฐ์ฐ ๋ถ๋ถ์์ ์ฒ๋ฆฌํ๋ค. ํ์ง๋ง, ์ด ๋ถ๋ถ์์๋ ์๋ฌด๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ์ง ๋ชปํ๋ค. ๊ทธ๋์ ์ค๊ฐ ์ฐ์ฐ(intermediate operation)์ด๋ผ๊ณ ํ๋ค. ์ค๊ฐ ์ฐ์ฐ์ ๋ฐ๋์ ์์ด์ผ ํ๋ ๊ฒ์ ์๋๋ค.
- ์ข ๋จ ์ฐ์ฐ : ๋ง์ง๋ง์ผ๋ก ์ค๊ฐ ์ฐ์ฐ์์ ์์ ๋ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํด ์ค๋ค. ๊ทธ๋์ ์ด ๋ถ๋ถ์ ์ข ๋จ ์ฐ์ฐ(terminal operation)์ด๋ผ๊ณ ํ๋ค.
์คํธ๋ฆผ์์๋ ๋ง์ ์ข ๋ฅ์ ์ฐ์ฐ์๊ฐ ์์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉํ๋ forEach(), map(), filter() ์ ๋๋ง ๋ณผ ์์ ์ด๋ค. ์ด ์ธ๊ฐ์ง ์ฃผ์ ๋ฉ์๋๋ค์ ํตํด์ ์ด๋ป๊ฒ ํ์ฉํ๋์ง ์ตํ๋ณด์.
๐กforEach()
forEach()๋ ์ข ๋จ ์ฐ์ฐ์ ์ํ๋ค.
ํ์์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ StudentDTOํด๋์ค๊ฐ ์๋ค๊ณ ํ ๋, ํด๋น ํด๋์ค์ ๊ฐ๊ฐ ์ ๋ณด๋ฅผ ๋ฃ์ด์ฃผ๊ณ , printStudentNames ๋ฉ์๋๋ฅผ ๋ํด ํ์์ ์ด๋ฆ์ ์ถ๋ ฅํ๋๋ก ํ๋ค. ์์ธํ ์ค๋ช ์ ์ฃผ์์ ์ฐธ๊ณ ํ์.
package stream; import java.util.ArrayList; import java.util.List; public class StudentForEachSample { public static void main(String[] args) { StudentForEachSample sample = new StudentForEachSample(); List<StudentDTO> studentList = new ArrayList<>(); studentList.add(new StudentDTO("์๋ค", 43, 99, 10)); studentList.add(new StudentDTO("๋ง๋", 30, 71, 85)); studentList.add(new StudentDTO("์ฐ๋นต", 32, 81, 75)); sample.printStudentNames(studentList); } public void printStudentNames(List<StudentDTO> studentList) { //1) DTO List์์ forEach๋ฅผ ํตํด์ ๊ฐ๊ฐ์ DTO๋ฅผ ๋ฝ์๋ด์, ๋ณ์์ ๋ด์์, ๊ฑ์ getName์ ์ถ๋ ฅ studentList.stream().forEach(student -> System.out.println(student.getName())); //2) DTO List๋ฅผ List<String>์ ํํ๋ก ๋ฐ๊ฟ์ forEach๋ก ๋ฝ๋๋ค. //์ฌ๊ธฐ์ map()์ "๋ฐ์ดํฐ๋ฅผ ํน์ ๋ฐ์ดํฐ๋ก ๋ณํ" ํ๋ ์ญํ ์ ํ๋ค. studentList.stream().map(student -> student.getName()).forEach(name -> System.out.println(name)); } }
์ฐธ๊ณ ๋ก ์ฃผ์์์ 2๋ฒ์ map๊ณผ forEach์ ์ถ๋ ฅ ๋ฌธ์ฅ์ ๊ฐ๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์ฒ๋ฆฌํ ์๋ ์๋ค.
map(StudentDTO::getName) forEach(System.out::println)
์ฒ์๋ณด๋ "๋๋ธ ์ฝ๋ก (::)"์ด ๋์๋ค. ์ด ์ญ์ Java 8์์ ์ถ๊ฐ๋ ๊ฒ์ธ๋ฐ, ์ด ๋๋ธ ์ฝ๋ก ์ Method Reference๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ฆ, ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ ์๋ฏธํ๋ค.
์ฌ๊ธฐ์ ๋ํด์๋ ์ดํด๋ณด๊ณ ๊ฐ๋๋ก ํ์.
๐กMethod Reference
๋ฉ์๋ ์ฐธ์กฐ๋ 4๊ฐ์ง ์ข ๋ฅ๊ฐ ์๋ค.
์ข ๋ฅ ์ static ๋ฉ์๋ ์ฐธ์กฐ ContainingClass::staticMethodName ํน์ ๊ฐ์ฒด์ ์ธ์คํด์ค ๋ฉ์๋ ์ฐธ์กฐ ContainingObject::instanceMethodName ํน์ ์ ํ์ ์์์ ๊ฐ์ฒด์ ๋ํ ์ธ์คํด์ค ๋ฉ์๋ ์ฐธ์กฐ ContainingType::methodName ์์ฑ์ ์ฐธ์กฐ ClassName::new ๐static ๋ฉ์๋ ์ฐธ์กฐ
package stream; import java.util.stream.Stream; public class MethodReferenceSample { public static void main(String[] args) { MethodReferenceSample sample = new MethodReferenceSample(); String[] stringArray = {"์๋ค", "๋ง๋", "์ฐ๋นต"}; sample.staticReference(stringArray); } private static void printResult(String value){ System.out.println(value); } private void staticReference(String[] stringArray) { Stream.of(stringArray).forEach(MethodReferenceSample::printResult); } }
staticReference() ๋ฉ์๋๋ฅผ ๋ณด๋ฉด forEach()๋ด์์ MethodReferenceSample::printResult๋ก ํธ์ถํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ด ์์ ์์๋ String์ ์คํธ๋ฆผ์ด๊ธฐ ๋๋ฌธ์ forEach() ๋ฌธ์ฅ ์์์๋ String์ ์ ๊ณตํ๋ค. ๊ทธ๋์ printResult() ๋ฉ์๋์์๋ String ๊ฐ์ ๋งค๊ฐ ๋ณ์๋ก ๋ฐ๊ธฐ ๋๋ฌธ์ ์ด์ฒ๋ผ ์ฐธ์กฐํด์ ์ฌ์ฉํ ์ ์๋ค.
๐ํน์ ๊ฐ์ฒด์ ์ธ์คํด์ค ๋ฉ์๋ ์ฐธ๊ณ
์ธ์คํด์ค ์ฐธ์กฐ๋ System.out::println๊ณผ ๊ฐ์ด System ํด๋์ค์ ์ ์ธ๋ out ๋ณ์๊ฐ ์๊ณ , ๊ทธ out๋ณ์์ ์๋ println() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ฒ๋ผ "๋ณ์์ ์ ์ธ๋ ๋ฉ์๋ ํธ์ถ"์ ์๋ฏธํ๋ค.
๐ํน์ ์ ํ์ ์์์ ๊ฐ์ฒด์ ๋ํ ์ธ์คํด์ค ๋ฉ์๋ ์ฐธ์กฐ
private void objectReference(String[] stringArray) { Arrays.sort(stringArray, String::compareToIgnoreCase); //์์ ๊ฐ์ฒด ์ฐธ์กฐ Arrays.asList(stringArray).stream().forEach(System.out::println); //์ธ์คํด์ค ๋ฉ์๋ ์ฐธ์กฐ }
์์ ์ฒซ๋ฒ์งธ ์ฝ๋๋ฅผ ๋ณด๋ฉด, String::compareToIgnoreCase๋ผ๊ณ ์ ํ ์๋๋ฐ, ์์์ ๋ณธ ๊ฒ ์ฒ๋ผ static ์ฐธ์กฐ์ฒ๋ผ ์ฌ์ฉํ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ทธ๋ฐ๋ฐ, compareToIgnoreCase() ๋ฉ์๋๋ ์ฌ์ค ์ด๋ ๊ฒ ์ ์ธ๋์ด ์๋ค.
public int compareToIgnoreCase(String str) { return CASE_INSENSITIVE_ORDER.compare(this, str); }
๋ค์ ๋งํด, static ๋ฉ์๋๊ฐ ์๋์ง๋ง, ์ด์ ๊ฐ์ด ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
๐์์ฑ์ ์ฐธ์กฐ
interface MakeString { String fromBytes(char[] chars); } private void createInstance() { MakeString makeString = String::new; char[] chars = {'G', 'o', 'd', 'O', 'f', 'J', 'a', 'v', 'a'}; String madeString = makeString.fromBytes(chars); System.out.println(madeString); }
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด MakeString makeString = String::new; ๋ผ๋ ๋ถ๋ถ์ด ๋ณด์ธ๋ค. ์ด๋ ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ์ด์ ๋ String์ ์์ฑ์ ์ค์์ char[]์ ๋งค๊ฐ ๋ณ์๋ก ๋ฐ๋ ์์ฑ์๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฌผ๋ก String์ ์ด๋ ๊ฒ ์ฌ์ฉํ๋ ๋ถ๋ค์ ๋ณ๋ก ์๊ฒ ์ง๋ง, ํ์์ ๋ฐ๋ผ์ ์ฌ๋ฌ ๊ฐ์ง ์์ฑ์๋ฅผ ์ ๋ง๋๋ก ์ธํฐํ์ด์ค๋ก ๋ง๋ค์ด ๋์ ์ ์๋ค.
๐กmap()
map()์ ์ค๊ฐ ์ฐ์ฐ์ ์ํ๋ค.
์ค๋ช ์ ์์ ๋ค์ ์ฝ๋๋ฅผ ๋ณด๊ณ , intList์ ์๋ ๋ด์ฉ๋ค์ ๋ชจ๋ 3๋ฐฐ์๋ก ๋ณํํด์ ์ถ๋ ฅํ๋ ์ฝ๋๋ฅผ ์คํธ๋ฆผ์ ์ด์ฉํด ์์ฑํด๋ณด์.
List<Integer> intList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
์ ๋ต
intList.stream().forEach(value -> System.out::println(value * 3));
๐๊ทธ๋ ๋ค๋ฉด, 3๋ฐฐ๋ก ๋ณํ๋ ๊ฐ๋ค์ ํฉ์ ๊ตฌํ๋ ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ์ข์๊น?
์ด๋ฐ ๊ฒฝ์ฐ, ์คํธ๋ฆผ์ ๊ฐ ์์ฒด๋ฅผ ๋ณํํด ๋ฒ๋ฆฌ๋ map()์ ์ฌ์ฉํ๋ฉด ๋๋ค.
intList.stream().map(x->x*3).forEach(System.out::println);
์์ ์ฝ๋๋ฅผ ๋ถ์ํด๋ณด๋ฉด ์ด๋ ๋ค.
map()์ผ๋ก ๋ณํ์ด ๋๋ ์๊ฐ ํด๋น ์คํธ๋ฆผ์ ๋ค์ ๊ตฌ๋ฌธ์ ์๋ ๋ด์ฉ๋ค์ด ๋ฐ๋์ด ๋ฒ๋ฆฐ๋ค.
์ฆ, ์ด๋ ๊ฒ ์ฌ์ฉํ๋ฉด ์คํธ๋ฆผ์์ ์ฒ๋ฆฌํ๋ ๊ฐ๋ค์ ์ค๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค. ์ด map()์ ์ซ์๋ฟ๋ง ์๋๋ผ ๊ฐ์ฒด๋ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
๊ทธ๋ผ ๋ง์ง๋ง์ผ๋ก ์๋์ ์ฝ๋๋ฅผ ์คํธ๋ฆผ์ ์ด์ฉํด ์ด๋ฆ๋ง์ List๋ก ๋ฝ์ ๋ด๋ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์.
(ํํธ: ์ข ๋จ ์ฐ์ฐ์๋ ์ํ๋ ํ์ ์ผ๋ก ๋ฆฌํด์ ํด์ฃผ๋ collect๋ฉ์๋๋ฅผ ์ด์ฉํ๋ค. collect(Collectors.toList());
List<StudentDTO> studentList = new ArrayList<>(); studentList.add(new StudentDTO("์๋ค", 43, 99, 10)); studentList.add(new StudentDTO("๋ง๋", 30, 71, 85)); studentList.add(new StudentDTO("์ฐ๋นต", 32, 81, 75));
์ ๋ต
List<String> nameList = studentList.stream() .map(student -> student.getName()).collect(Collectors.toList());
๐กfilter()
filter๋ผ๋ ๋จ์ด๋ ๋ฌด์ธ๊ฐ๋ฅผ ๊ฑธ๋ฌ๋ธ๋ค๋ ๋ป์ผ๋ก ์ฐ์ธ๋ค. ํ๋ก๊ทธ๋๋ฐ์์๋ ๋์ผํ๊ฒ ์ฌ์ฉ๋๋ค. ์ฆ, ํ์ ์๋ ๋ฐ์ดํฐ๋ ์น ์์ฒญ๋ค์ ๊ฑธ๋ฌ๋ผ ๋ ์ฌ์ฉํ๋ค.
package stream; import java.util.ArrayList; import java.util.List; public class StudentFilterSample { public static void main(String[] args) { StudentFilterSample sample = new StudentFilterSample(); List<StudentDTO> studentList = new ArrayList<>(); studentList.add(new StudentDTO("์๋ค", 43, 99, 10)); studentList.add(new StudentDTO("๋ง๋", 30, 71, 85)); studentList.add(new StudentDTO("์ฐ๋นต", 32, 81, 75)); sample.filterWithScoreForLoop(studentList, 80); } public void filterWithScoreForLoop(List<StudentDTO> studentList, int scoreCutLine) { for(StudentDTO student:studentList) { if(student.getScore()>scoreCutLine) { System.out.println(student.getName()); } } } }
์์ ์ฝ๋์์๋ filterWithScoreForLoop๋ฅผ ํตํด 80์ ์ด์์ ์ ์๋ฅผ ๊ฐ๋ ์ฌ๋๋ง ์ด๋ฆ์ ์ถ๋ ฅํ๋๋ก ํ๋ค. ํด๋น ๋ฉ์๋๋ฅผ ์คํธ๋ฆผ์ผ๋ก ๊ตฌํํด๋ณด๋ฉด ์ด๋ ๊ฒ ๋์จ๋ค.
studentList.stream() .filter(student -> student.getScoreMath() > scoreCutLine) .forEach(student -> System.out.println(student.getName()));
studentList๋ฅผ ์คํธ๋ฆผ ์ฒ๋ฆฌ ํ๊ณ , ๊ฐ๋ณ ํ์์ ์ ์๊ฐ scoreCutLine๋ณด๋ค ํฐ ํ์๋ง ๊ทธ ๋ฐ์ forEach() ๊ตฌ๋ฌธ์ผ๋ก ์ด๋ํ๋ค. ๊ทธ๋์ ๊ฒฐ๊ณผ๋ ์์ for ๋ฃจํ๋ฅผ ์ฌ์ฉํ ๊ฒ๊ณผ ๊ฐ๋ค.
์ฆ, filter๋ if๋ฌธ์ฒ๋ผ ์คํธ๋ฆผ ๋ด์์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฑธ๋ฌ์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค.
๐ก์ ๋ฆฌํ๋ฉฐ
์ค์ ๋ก ํ์ ์์ ๊ฐ๋ฐํ๋ฉด์, ๋๋คํํ์์ด๋ ์คํธ๋ฆผ์ ์จ๋ณธ์ ์ ์๋ค๋ณด๋(์์ผ๋ก ์๊ธธ์ง๋ ๋ชจ๋ฅด์ง๋ง), ํด๋น ๊ธ์ ์ฝ๋๋ฐ ๋น์ฅ ์ฌ์ฉํ ๋ฌธ๋ฒ์ด ์๋๋ค๋ณด๋, ๋ฌด์ธ๊ฐ ์๋ฟ์ง์์(?)์ผ๋ก ์ธํด ์ฝํ์ง ์์ ํ๋ฃจ์ข ์ผ ๊ณ ์ํ๋ค.. ๊ทธ๋๋ ๋ธ๋ก๊ทธ์ ์ ๋ฆฌ๋ฅผ ํ๋ฉด, ์ข ์ฝํ ๊ฒ ๊ฐ์์ ์ด๋ ๊ฒ ์ ๋ฆฌ๋ฅผ ํ๋ฉฐ ๊ณต๋ถ๋ฅผ ํด๋ณด์๋ค. ํ์ง๋ง, ์๊ณ ์๋ ๊ฒ๊ณผ ๋ชจ๋ฅด๊ณ ์๋๊ฒ์ ๋ํ ์ฐจ์ด๋ ํฌ๋ค๊ณ ์๊ฐํ๋ค. ๋ ์ฑ ์์ ์ ํ ๋ด์ฉ ์ฒ๋ผ ๋ด๊ฐ ์ต์ํด์ง๋ฉด ํธํ ์๋ ์๊ณ , ๋ ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด์ง๋ ์ฅ์ ์ด ์์ ๊ฒ์ด๋ค :)
๐Reference
- ์๋ฐ์ ์
'๊ฐ๋ฐ > Java' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JVM์ด์ผ๊ธฐ - ์ ์(+JRE, JDK), ๊ตฌ์กฐ (0) 2022.07.05 ์๋ฐ๊ฐ ํ์ฅํ ๊ฐ์ฒด ์งํฅ (0) 2022.05.24 Java8 - Lamda ํํ์(expression) (0) 2022.04.29 [Thread] Runnable and Callable in Java (0) 2022.04.25 [Thread] Volatile์ด๋, Volatile๊ณผ DCL(Double Checking Locking) ๊ณต๋ถ ๊ธฐ๋ก (0) 2022.04.24