diff --git "a/7\354\236\245/45_\354\212\244\355\212\270\353\246\274\354\235\200_\354\243\274\354\235\230\355\225\264\354\204\234_\354\202\254\354\232\251\355\225\230\353\235\274_\353\260\225\354\206\214\354\240\225.md" "b/7\354\236\245/45_\354\212\244\355\212\270\353\246\274\354\235\200_\354\243\274\354\235\230\355\225\264\354\204\234_\354\202\254\354\232\251\355\225\230\353\235\274_\353\260\225\354\206\214\354\240\225.md" new file mode 100644 index 0000000..619c4ab --- /dev/null +++ "b/7\354\236\245/45_\354\212\244\355\212\270\353\246\274\354\235\200_\354\243\274\354\235\230\355\225\264\354\204\234_\354\202\254\354\232\251\355\225\230\353\235\274_\353\260\225\354\206\214\354\240\225.md" @@ -0,0 +1,169 @@ +# 스트림은 주의해서 사용하라 + +--- + +스트림은 다량의 데이터 처리 작업을 돕고자 java 8 에 추가되었다. + +## 💡스트림의 핵심 개념 2가지 + +- 데이터 원소의 무한 또는 유한 시퀀스(순서있는 나열) +- 스트림 파이프 라인 : 원소들로 수행하는 연산 단계 + +## 스트림 파이프 라인 + +- 소스 스트림 - 중간 연산(스트림을 변환 ex: 조건, 함수 적용) - 종단 연산 +- 지연 평가(lazy evaluation) : 종단 연산이 수행될 때 평가된다 - 종단 연산이 수행되지 않으면 아무일도 일어나지 않는다. +- 일단 한 값을 다른 값에 매핑하고 나면 원래의 값은 잃는 구조 + +## 지연 평가(lazy evaluation) + +그때 그때 값을 평가하지 않고, 정말 결과값이 필요한 시점까지 평가를 미루는 것 + +1. 필요할 때만 평가가 되므로 메모리를 효율적으로 사용할 수 있다. +2. 무한 자료구조를 만들 수 있음 +3. 런타임 에러를 방지 할 수 있다. ( 컴파일 시 에러를 체킹) +4. 컴파일러 최적화 가능 + +[지연 평가 링크](http://filimanjaro.com/blog/2014/introducing-lazy-evaluation/) + +```java +public static void main(String[] args) { + List numList = Arrays.asList(10, 20, 30, 40, 50, 60); + System.out.println(numList.stream() + .filter(num -> { + System.out.println("num < 50"); + return num < 50; + }) + .filter(num ->{ + System.out.println("num < 30"); + return num < 30; + }) + .map(num ->{ + System.out.println("num * 100"); + return num * 100; + }) + .collect(Collectors.toList()) + ); + } +``` + +```java +/** +num < 50 +num < 30 +num * 100 +num < 50 +num < 30 +num * 100 +num < 50 +num < 30 +num < 50 +num < 30 +num < 50 +num < 50 +[1000, 2000] +**/ +``` + +## 반복문의 장점(코드 블럭 사용의 장점) + +스트림 → 함수 객체 사용 + +반복문 → 코드 블록 사용 + +- 범위 안의 지역 변수를 읽고 수정이 가능 +- break, continue를 활용하여 반복문을 종료, 반복을 뛰어 넘을 수 있음 +- 메서드 선언에 예외 처리가 가능함 + +## 스트림을 사용을 추천하는 경우 + +- 원소들의 시퀀스를 일관되게 변환하는 경우 +- 원소들의 시퀀스를 필터링하는 경우 +- 원소들의 시퀀스를 하나의 연산을 사용해 결합하는 경우 +- 원소들의 시퀀스를 컬렉션에 모으는 경우(공통된 속성을 기준으로) +- 원소들의 시퀀스에서 특정 조건을 만족하는 원소를 찾는 경우 + +--- + +## 스트림을 사용하여 가독성이 높아진 예제 + +```java +public static void main(String[] args) { + File dectionary = new File(args[0]); + int minGroupSize = Integer.parseInt(args[1]); + + Map> groups = new HashMap<>(); + try (Scanner s = new Scanner(dectionary)) { + while(s.hasNext()) { + String word = s.next(); + groups.computeIfAbsent(alphabetize(word), + (unused) -> new TreeSet<>()).add(word); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + for(Set group : groups.values()) { + if(group.size() >= minGroupSize) { + System.out.println(group.size() + ": " + group); + } + } +} + +private static String alphabetize(String s) { + char[] a = s.toCharArray(); + Arrays.sort(a); + return new String(a); +} +``` + +- computeIfAbsent 함수: 맵 안에 키가 있는지 찾은 후, 있으면 단순히 키가 매핑된 값을 반환한다. + +```java +public static void main(String[] args) throws IOException { + File dectionary = new File(args[0]); + int minGroupSize = Integer.parseInt(args[1]); + + try(Stream words = Files.lines(dectionary.toPath())) { + words.collect(groupingBy(word -> alphabetize(word))) + .values().stream() + .filter(group -> group.size() >= minGroupSize) + .forEach(group -> System.out.println(group.size() + ": " + group)); + } +} +``` + +😡스트림을 과용하면 프로그램을 읽거나 유지보수하는 것이 어려워 진다. + +💡람다 사용시 매개변수의 변수를 잘 지어야 스트림 파이프 라인의 가독성이 올라간다. + +--- + +## 스트림과 반복 중 어떤 쪽을 써야할지 알기 어려운 경우 + +데카르트 곱 : 가능한 모든 조합을 구하는 경우 + +```java +private static List newDeck() { + List result = new ArrayList<>(); + for(Suit suit : Suit.values()) + for(Rank rank : Rank.values()) + result.add(new Card(suit, rank)); + return result; +} +``` + +```java +private static List newDeck() { + return Stream.of(Suit.values()) + .flatMap(suit -> Stream.of(Rank.values()) + .map(rank -> new Card(suit, rank))) + .collect(toList()); +} +``` + +두 가지 경우가 있는데, 제 기준 반복을 활용한 코드가 더 가독성이 높았습니다. + +--- + +## 🤷‍♀️Stream과 반복중 어느 쪽이 더 유리한지 확신이 서지 않을 경우, 둘 다 해보고 더 나은 쪽을 선택하기! \ No newline at end of file