2023-03-20 37일차 자바

37일

17 전기

컬렉션 항목은 종종 반복적으로 처리됩니다.
이 Stream API 메서드는 코드를 단순화합니다.

17.7 중간 처리

중간 처리 작업이 결국 즉시 수행되기 위해서는 최종 작업이 수행되어야 합니다.
특별한 것이 없다면 메소드 체이닝으로 하는 것이 좋다.
코드를 읽기 어렵고 부분적으로 작성하는 것이 편리하다면 부분적으로 작성할 수 있습니다.
중간 작업은 마지막 작업이 실행될 때 즉시 실행됩니다.
최종 처리 전 중간에 값을 입력하면 값이 입력되고 즉시 중간 작업이 수행됩니다.

반환 유형: 스트림
제한: 크기 제한
clear: 중복 제거
peek : 중간 처리 작업( foreach 와 비교)
filter : 필터링하다
map : 매핑(다른 요소에 매핑)
flatmap : 매핑(다른 요소에 매핑)
boxed: 기본 typestream에서 참조 typestream으로 변환
정렬하다: 정렬하다

17.7.1 중간 동작 제한: 크기 제한

스트림으로 흐르는 항목의 크기(수)를 제한합니다.

public class C02Limit {
    public static void main(String() args) {
        List<String> list = List.of("java", "css", "html", "spring", "jsp");

        Stream<String> stream1 = list.stream();
        Stream<String> stream2 = stream1.limit(3); // 스트림 원소 중 3개로 제한

        long count = stream2.count();

        System.out.println(count);

        long count2 = list.stream()
                .limit(3)
                .count();

        System.out.println(count2);
    }
}

17.7.2 unique: 중복 제거

스트림에서 중복 항목을 제거합니다.

public class C03Distinct {
    public static void main(String() args) {
        // limit 중간연산 : 크기제한
        List<Integer> list = List.of(3, 1, 2, 0, 1, 2, 3);

        long count = list.stream()
                .count();

        System.out.println(count); // 7

        long count2 = list.stream()
                .distinct()
                .count();

        System.out.println(count2); // 4
    }
}

17.7.3 명확하게 – 2

로또 번호를 생성하기 위해 1부터 45까지 6개의 숫자를 무작위로 선택하는 프로그램을 만들어 봅시다.
숫자를 무한대로 생성하는 코드 작성
여기에서 중복 제거 -> 제한 6

public class C05Distinct {
    public static void main(String() args) {
        // 1~45 로또번호 뽑기
        Stream<Integer> stream = Stream.generate(() -> (int) (Math.random() * 45) + 1);

        stream
                .distinct()
                .limit(6)
                .forEach(System.out::println);

        // Random Class 사용
        Random random = new Random();
        Stream.generate(() -> random.nextInt(45) + 1)
                .distinct()
                .limit(6)
                .forEach(System.out::println);
    }
}

17.7.4 엿보기()

foreach와 유사하게 작동합니다.
스트림을 반환
소비자 유형 인터페이스를 매개변수로 받습니다.
이는 기능적 인터페이스이며 Accept(T t) 매개변수를 사용하고 .

forEach는 마지막 작업을 처리하는 데 사용됩니다.
Peek는 중간에 작업이 잘 진행되고 있는지 시각적으로 확인하려는 경우 오류를 발견하는 데 자주 사용됩니다.
디버깅 목적으로 자주 사용됩니다.

public class C06Peek {
    public static void main(String() args) {
        // peek
        // 랜덤한 인티저 값 생성
        // 한꺼번에 일하기 때문에 2번씩 5번 출력
        new Random().ints(5)
                .peek(System.out::println)
                .forEach(System.out::println);
    }
}

17.7.5 필터()

자주 사용 필터링 및 분류 작업을 수행합니다.
Predicate 인터페이스를 매개변수로 사용하여 Stream을 반환합니다.
추상 메서드 테스트(T t)가 있습니다.
매개변수를 하나씩 취하고 각 요소에 대해 부울 유형을 반환합니다.
참이면 살아남고 거짓이면 걸러냅니다.

public class C07Filter {
    public static void main(String() args) {
        // filter : 걸러내기
        List<Integer> list = List.of(3, 9, -1, 0, 2, -3, -6, 7, 8);

        System.out.println("양수만##");
        list.stream()
                .filter(s -> s > 0)
                .forEach(System.out::println);

        System.out.println("짝수만##");
        list.stream()
                .filter(s -> s % 2 == 0)
                .forEach(System.out::println);

        System.out.println("홀수만##");
        list.stream()
                .filter(s -> s % 2 != 0)
                .forEach(System.out::println);
    }
}

17.7.6 검증 문제 #5

목록에 스트림으로 기록됩니다.
Java가 포함된 경우 대소문자를 구분하지 않고 필터링하여 출력합니다.
1. 고전적인 for 문으로 쓰기
2. 스트림 API 사용해보기

public class Example {
    public static void main(String() args) {
        List<String> list = Arrays.asList(
                "This is a java book",
                "Lambda Expressions",
                "Java8 supprots lambda expressions");

        // 고전 for
        for (String s : list) {
            if (s.toLowerCase().contains("java")) {
                System.out.println(s);
            }
        }

        //stream
        list.stream()
                .filter(s -> s.toLowerCase().contains("java"))
                .forEach(s -> System.out.println(s));
    }
}

17.7.7 맵()

작업은 한 요소를 다른 요소로 매핑(변환)하는 것입니다.
함수 인터페이스를 매개변수로 받습니다.
추상 메소드 apply(T t)가 있습니다.
매개변수를 받아 리턴값을 리턴하지만 매개변수의 유형과 리턴 유형이 다릅니다.
T 유형을 사용하고 유형 R을 리턴합니다.
매개변수로 입력된 요소는 스트림 요소이며 반환되는 것은 다음에 사용할 스트림입니다.

할당된 스트림은 다음 스트림에서 사용됩니다.

public class C08Map {
    public static void main(String() args) {
        // map : 매핑(변환)
        List<Integer> list = List.of(2, 1, 0, 3, 9);

        System.out.println("0으로 매핑 ####");
        list.stream()
                .map(e -> 0)
                .forEach(System.out::println);

        System.out.println("*2(짝수)로 매핑 ####");
        list.stream()
                .map(e -> e * 2)
                .forEach(System.out::println);
    }
}

17.7.7 지도() -2

원본 스트림이 문자열이면 매핑도 문자열이어야 합니다 -> 그렇지 않습니다.
함수가 반환하는 것은 다른 반환 유형을 반환할 수 있습니다.
원래 요소와 동일한 유형일 수 없습니다.

문자열 스트림을 정수 스트림으로 변환할 수 있습니다.

public class C10Map {
    public static void main(String() args) {
        // map : 매핑(변환)
        List<String> list = List.of("java", "html", "css", "spring");

        Stream<String> stream1 = list.stream();

        // 다른 타입으로 매핑
        Stream<Integer> stream2 = stream1.map(s -> s.length());
        stream2.forEach(System.out::println);

        System.out.println("짝수 길이 스트링만 출력###");
        long count = list.stream()
                .map(s -> s.length())
                .filter(s -> s % 2 == 0)
                .count();
        System.out.println(count); //3
    }
}

17.7.8 지도() -3

IntStream에는 이미 값을 줄이는 메서드가 있습니다.
어렵게 정의하고 사용하지 않고 리듀스만 사용하고 싶다면,
스트림을 인스트림으로 변경할 수 있습니다.

그냥 mapToInt()를 하세요.
추상 메서드 applyAsInt가 있는 인터페이스를 매개 변수로 사용하고 int를 반환합니다.
따라서 intStream으로 변경할 수 있습니다.

Mapxxx() 메서드가 있습니다.
즉, 참조형 스트림이 아닌 기본형 스트림으로 변경될 수 있다.

public class C11Map {
    public static void main(String() args) {
        List<Book> list = List.of(
                new Book("salmdunk", 3000),
                new Book("avatar", 4000),
                new Book("theh glory", 5000),
                new Book("avengers", 2000));

        int sum = list.stream()
                .map(b -> b.getPrice())
                .reduce((a, b) -> a + b)
                .get();

        System.out.println(sum); //14000

        double avg = list.stream()
                .mapToInt(Book::getPrice)
                .average()
                .getAsDouble();

        System.out.println(avg); //3500.0
    }
}

17.7.9 지도() -4

mapToInt 연습
최대 점수 최소 점수 전체 평균
summaryStatistics() 메서드는 IntSummaryStatistics 개체를 반환합니다.
IntStream의 개수, 합계, 최소값, 평균값 및 최대값을 저장하는 개체입니다.

public class MapExample {
    public static void main(String() args) {
        // List컬렉션 생성
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("홍길동", 85));
        studentList.add(new Student("홍길동", 92));
        studentList.add(new Student("홍길동", 87));

        // Student를 score 스트림으로 변환
        studentList.stream()
                .mapToInt(s -> s.getScore())
                .forEach(score -> System.out.println(score));

        int max = studentList.stream()
                .mapToInt(s -> s.getScore())
                .max()
                .getAsInt();

        int min = studentList.stream()
                .mapToInt(s -> s.getScore())
                .min()
                .getAsInt();

        int sum = studentList.stream()
                .mapToInt(s -> s.getScore())
                .sum();

        double avg = studentList.stream()
                .mapToInt(s -> s.getScore())
                .average()
                .getAsDouble();

        System.out.printf("최대점수: %d, 최소점수: %d, 총합: %d, 평균: %f\n", max, min, sum, avg);
        //최대점수: 92, 최소점수: 85, 총합: 264, 평균: 88.000000

        // summaryStatistics() : 통계
        IntSummaryStatistics summary = studentList.stream()
        .mapToInt(s -> s.getScore())
        .summaryStatistics();

        System.out.println(summary);
        //IntSummaryStatistics{count=3, sum=264, min=85, average=88.000000, max=92}
    }
}

결과적으로
동일한 유형에 할당할 수 있습니다.
완전히 다른 종류의 참조 유형에 매핑할 수도 있습니다.
또한 기본 유형 스트림에 참조 유형을 할당할 수 있습니다.

2010년 7월 17일 검토 질문 #6

목록에 있는 구성원의 평균 연령을 가져옵니다.

public class Example {
    public static void main(String() args) {
        List<Member> list = Arrays.asList(
                new Member("홍길동", 30),
                new Member("신용권", 40),
                new Member("감자바", 26));

        // 고전for
        System.out.println("고전for문 사용");
        int sum = 0;
        for (Member m : list) {
            sum += m.getAge();
        }
        double avg = (double) sum / list.size();
        System.out.println("평균나이: " + avg); // 32.0

        // stream
        System.out.println("IntStream, average 사용###");
        avg = list.stream()
                .mapToInt(m -> m.getAge())
                .average()
                .getAsDouble();
        System.out.println("평균나이: " + avg); // 32.0

        System.out.println("stream, collect 사용###");
        avg = list.stream()
                .collect(Collectors.averagingDouble(Member::getAge));
        System.out.println("평균나이: " + avg);
    }
}

17.7.11 지도 – 5위

참조 유형 -> 기본 유형 매핑을 만들었습니다.
반대로 기본 유형 -> 참조 유형 매핑을 수행합니다.
mapToObj() 메소드
기본 유형 int를 사용하여 참조 유형으로 반환합니다.

기본 유형을 참조 유형으로 변환해야 하는 경우가 많습니다.
mapToObj()는 모든 참조 유형으로 변환될 수 있습니다.

public class C12Map {
    public static void main(String() args) {
        //기본타입 int가 원소 스트림
        IntStream stream1 = IntStream.range(11, 20);

        //참조타입 Intger가 원소인 스트림으로 변환
        Stream<Integer> stream2 = stream1.mapToObj(Integer::valueOf);
        long count = stream2.count();
        System.out.println(count);
    }
}

그러나 특별히 Integer로 변경하려는 경우 boxed() 를 사용할 수 있습니다.
스트림 제공 반품.

public class C13Map {
    public static void main(String() args) {
        // boxed :
        // 기본타입을 원소로 갖는 stream
        // --> 참조타입을 원소로 갖는 stream 변환
        IntStream stream1 = IntStream.range(1, 10);
        Stream<Integer> stream2 = stream1.boxed();

        DoubleStream stream3 = DoubleStream.of(3.14, 9.99);
        Stream<Double> stream4 = stream3.boxed();
    }
}

의심?
Count 등은 기본 유형 스트림에서도 사용할 수 있습니다.
하지만 왜 그것을 포함하기 위해 boxed()를 사용합니까?
int 자체는 컬렉션에 저장할 수 없기 때문입니다.
Integer 클래스로 변환하여 List로 저장하는 등의 기능을 수행하기 위해 존재합니다. 실행하다.

intStream = Arrays.stream(intArray);
List<Integer> r1 = intStream.boxed()
        .collect(Collectors.toList());
System.out.println(r1);

17.7.12 플랫맵()

매핑과 유사합니다. map은 원래 요소의 일대일 매핑입니다.
flatMap은 원래 요소를 다른 요소에 대한 일대다 매핑입니다.
flatMap()은 함수 인터페이스를 매개변수로 받습니다.
지도와 마찬가지로 1개의 입력과 1개의 반환이 있습니다.
반환은 스트림 또는 그 하위 유형이어야 합니다. 즉, 스트림을 반환하는 중간 프로세스입니다.

하나를 가져와 다중 요소 스트림으로 바꿉니다.

public class C14FlatMap {
    public static void main(String() args) {
        // flatMap:
        // 원래 원소를 다른 원소 '들'로 매핑

        List<Integer> list = List.of(3, 4, 5);

        // map: 1 대 1
        long count1 = list.stream()
                .map(e -> e)
                .count();
        System.out.println(count1); // 3

        // flatMap : 1 대 다(0이상)
        long count2 = list.stream()
                .flatMap(e -> Stream.of(0, 0)) // 각 값이 들어와서 두개짜리 stream으로 만듬
                .count();
        System.out.println(count2); //6
    }
}

17.7.12 플랫맵() – 2

공백으로 구분된 단어의 수를 세고 싶습니다.
첫 번째 요소를 배열로 만들고 스트림을 만듭니다.
두 번째 요소를 배열 및 스트림으로 만들기
flatMap은 이러한 스트림을 단일 스트림으로 병합합니다.

public class C15FlatMap {
    public static void main(String() args) {
        List<String> list = List.of(
                "hello world",
                "java program",
                "css html js");

        long count = list.stream()
                .flatMap(s -> Arrays.stream(s.split(" ")))
                .count();
        System.out.println(count); // 7
    }
}

flatMap은 스트림까지 반환됩니다.
flatMapToInt는 int 스트림을 반환하고 flatMapToDouble은 이중 스트림을 반환합니다.

List<String> list2 = Arrays.asList("10, 20, 30", "40, 50");
list2.stream()
        .flatMapToInt(data -> {
            //Steam배열을 int배열로 만듬
            String() strArr = data.split(",");
            int() intArr = new int(strArr.length);
            for (int i = 0; i < strArr.length; i++) {
                intArr(i) = Integer.parseInt(strArr(i).trim());
            }
            //Arrays.stream()메소드는 주어진 인트배열을 IntStream으로 만듬
            return Arrays.stream(intArr);
        })

list2.stream()
        .flatMap(data -> Arrays.stream(data.split(",")))
        .map(s -> s.trim())
        .mapToInt(s -> Integer.parseInt(s))
        .forEach(System.out::println);

13년 7월 17일 정렬됨

sorteds는 정렬된 스트림을 반환합니다.
정렬된 스트림을 자연스러운 순서로 반환합니다.

public class C16Sorted {
    public static void main(String() args) {
        // sorted : 정렬된 Stream return
        List<String> list = List.of(
                "chisoo",
                "backho",
                "taewoong",
                "taesup",
                "daeman");

        list.stream()
                .sorted()
                .forEach(System.out::println);
        // backho chisoo daeman taesup taewoong
    }
}

17.7.14 정렬 – 2차

정렬됨(비교기)
Comparator 인터페이스를 파라미터로 받는 메소드도 있습니다.
Comparator를 sroted()에 대한 매개변수로 람다 식으로 구현할 수 있습니다.

public class C17Sorted {
    public static void main(String() args) {
        List<Movie> movie = List.of(
                new Movie("avavtar", 10000),
                new Movie("slamdunk", 9000),
                new Movie("avengers", 7000),
                new Movie("titanic", 15000));

        movie.stream()
                .sorted((m1, m2) -> m1.getPrice() - m2.getPrice())
                .forEach(System.out::println);

        movie.stream()
        .sorted((m1, m2) -> m1.getTitle().compareTo(m2.getTitle()))
        .forEach(System.out::println);
    }
}

2014년 7월 17일 분류 – 3차

일반 순서가 정의되어 있어도 비교기가 구현되면 비교기가 우선합니다.

public class C18Sorted {
    public static void main(String() args) {
        List<Car> list = List.of(
                new Car("genesis", 7000),
                new Car("avante", 2500),
                new Car("tesla", 5000),
                new Car("morning", 1500));

        list.stream()
                .sorted()
                .forEach(System.out::println);

        System.out.println();

        list.stream()
                .sorted((a, b) -> a.getName().compareTo(b.getName()))
                .forEach(System.out::println);
    }
}

역정렬을 오버라이드(override)할 수도 있지만 역정렬의 경우가 많아 별도의 방법이 있다.
sorted(Comparator.reverseOrder()) 자연 순서의 역순으로 정렬합니다.
이것을 사용하려면 비슷한 것을 구현해야 합니다. 자연의 질서를 뒤집기 때문에

list.stream()
        .sorted((a, b) -> b.getPrice() - a.getPrice())
        .forEach(System.out::println);

list.stream()
        .sorted(Comparator.reverseOrder())
        .forEach(System.out::println);

15년 7월 17일 – 4번째

IntStream.range(1, 6)을 뒤집어 봅시다.
IntStream.range(1, 6).sorted((a, b) -> Integer.compare(b, a))
원하는 경우에도 intStream의 정렬된 Comparator는 이를 구현할 수 없습니다.
int 기본 유형은 상속될 수 없기 때문입니다.

따라서 기본 유형 스트림을 참조 유형 스트림에 매핑할 수 있습니다.

public class C19Sorted {
    public static void main(String() args) {
        // 5~1 출력
        IntStream.range(1, 6)
                .boxed() // .mapToObj(a -> a)
                .sorted((a, b) -> Integer.compare(b, a))
                // .sorted(Comparator.reverseOrder())
                .forEach(System.out::println);
    }
}

2016년 7월 17일 검토 질문 #7

직업이 개발자인 사람들을 모아 목록에 추가

public class Example {
    public static void main(String() args) {
        List<Member> list = Arrays.asList(
                new Member("홍길동", "개발자"),
                new Member("김나리", "디자이너"),
                new Member("신용권", "개발자"));

        // 고전적 for
        System.out.println("고전 for ####");
        List<Member> devlopers1 = new ArrayList<>();
        for (Member member : list) {
            if (member.getJob().equals("개발자")) {
                devlopers1.add(member);
            }
        }
        for (Member member : devlopers1) {
            System.out.println(member.getName());
        }

        // stream
        System.out.println("stream ####");
        List<Member> devlopers2 = list.stream()
                .filter(m -> m.getJob().equals("개발자"))
                .collect(Collectors.toList());

        devlopers2.stream()
                .forEach(m -> System.out.println(m.getName()));
    }
}

2023-03-20 검토

힘이 다했습니다. 앞으로 코드를 작성할 때 의도적으로 사용하려고 하면 잊어버리지 않을 것 같습니다.
사용하기 그렇게 어렵지는 않지만 잊어버리게 될 것입니다.