2022/02/25 자바의 다양한기능들

김석진·2022년 2월 25일
0

스트림(Stream)

스트림이란?

  • 자료의 대상과 관계없이 동일한 연산을 수행
    배열,컬렉션을 대상으로 연산을 수행함
    일관성 있는 연산으로 자료의 처리를 쉽고 간단하게 함
    자료 처리에 대한 추상화가 구현되었다고 함
  • 한번 생성하고 사용한 스트림은 재사용 할수 X
    자료에 대한 스트림을 생성하여 연산을 수행하면 스트림은 소모됨
    다른 연산을 수행하기 위해서는 스트림을 다시 생성해야함
  • 스트림 연산은 기존 자료를 변경하지 않음
    자료에 대한 스트림을 생성하면 스트림이 사용하는 메모리 공간은 별도로 생성되므로 연산이 수행되기도 기존 자료에 대한 변경은 발생하지 않음
  • 스트림 연산은 중간 연산과 최종연산으로 구분됨
    스트림에 대해 중간 연산은 여러 개의 연산이 적용될 수 있지만 최종 연산은 마지막에 한 번만 적용됨
    최종 연산이 호출되어야 중간 연산에 대한 수행이 이뤄지고 그 결과가 만들어짐
    따라서 중간 연산에 댈한 결과를 연산 중에 알수 X(이를 지연 연산)이라함

중간 연산과 최종 연산

  • 중간 연산의 예 -filter(),map(),sorted()등
    조건에 맞는 요소를 추출(filter)하거나 요소를 변환 함(map)
  • 최종 연산이 호출될 때 중간 연산이 수행되고 결과가 생성됨
  • 문자열 리스트에서 문자열의 길이가 5 이상인 요소만 출력하기
sList.stream().filter(s->s.length()>=5).forEach(s->System.out.println(s));

filter()는 중간연산, forEach()는 최종연산임

  • 고객 클래스 배열에서 고객 이름만 가져오기
customerList.stream().map(c->c.getName)).forEach(s->System.out.println(s));

map()은 중간 연산, forEach()는 최종연산

  • 종간 연산과 최종 연산에 대한 구현은 람다식을 활용
  • 최종 연산의 예 - forEach(), count(), sum() 등
    스트림이 관리하는 자료를 하나씩 소모해가며 연산이 수행 됨
    최종 연산 후에 스트림은 더 이상 다른 연산을 적용할 수 없음
    forEach(): 요소를 하나씩 꺼내옴
    count(): 요소의 개수
    sum(): 요소들의 합

연산 수행에 대한 구현을 할 수 잇는 reduce()연산

reduce()연산

  • 정의된 연산이 아닌 프로그래머가 직접 구현한 연산을 적용
T reduce(T identity, BinaryOperator<T> accumulator)

identity : 기본값
accumulator : 람다식을 쓸수도있다, BinaryOperator를 구현한 class를 쓸수 있다.
  • 최종 연산으로 스트림의 요소를 소모하며 연산을 수행
  • 배열의 모든 요소의 합을 구하는 reduce()연산의 구현 예
Arrays.stream(arr).reduce(0,(a,b)->a+b));
  • reduce()메서드의 두번째 요소로 전달되는 람다식에 따라 다양한 기능을 수행할 수 있음
  • 람다식을 직접 구현하거나 람다식이 긴경우 BinaryOperator를 구현한 클래스를 사용함

BinaryOperator를 구현하여 배열에 여러 문자열이 있을 떄 길이가 가장 긴 문자열 찾기 예

class CompareString implements BinaryOperator<String> {
    @Override
    public String apply(String s1, String s2) {
        if(s1.getBytes().length>=s2.getBytes().length) return s1;
        else return s2;
    }
}

public class ReduceTest {

    public static void main(String[] args) {
        String greetings[]={"안녕하세요","Hello","Bonjour","Good morning","반갑습니다."};

        //-reduce 람다식으로 설정한 예제
        System.out.println(Arrays.stream(greetings).reduce("",(s1,s2)->{
            if(s1.getBytes().length>=s2.getBytes().length) return s1;
            else return s2;
        }));

        
        //-reduce()에서 람다식이 길어졌을 경우 클래스로 만들어서 BinaryOperator를 구현한예
        System.out.println(Arrays.stream(greetings).reduce(new CompareString()).get());

    }
}

스트림을 활용하여 패키지 여행 비용 계산하기

문제 정의

여행사에 패키지 여행 상품이 있습니다. 여행 비용은 15세 이상은 100만원, 그 미만은 50만원 입니다.
고객 세 명이 패키지 여행을 떠난다고 했을 때 비용 계산과 고객 명단 검색등에 대한 연산을 스트림을 활용하여 구현해 봅니다.
고객에 대한 클래스를 만들고 ArrayList로 고객을 관리 합니다.
고객 정보는 다음과 같습니다.
CustomerLee
이름 : 이순신
나이 : 40
비용 : 100
CustomerKim
이름 : 김유신
나이 : 20
비용 : 100
CustomerHong
이름 : 홍길동
나이 :13
비용 : 50

스트림을 활용한 연산수행

  1. 고객의 명단을 출력
  2. 여행의 총 비용을 계산
  3. 고객 중 20세 이상인 사람의 이름을 정렬하여 출력
public class TravelCustomerTest {
    public static void main(String[] args) {
        TravelCustomer customerLee = new TravelCustomer("이순신", 40, 100);
        TravelCustomer customerKim = new TravelCustomer("김유신", 20, 100);
        TravelCustomer customerHong = new TravelCustomer("홍길동", 13, 50);

        ArrayList<TravelCustomer> list = new ArrayList<>();
        list.add(customerLee);
        list.add(customerKim);
        list.add(customerHong);

        System.out.println("고객 명단 출력");
        list.stream().map(c -> c.getName()).forEach(s -> System.out.println(s));

        System.out.println("\n여행 비용");
        System.out.println(list.stream().mapToInt(c -> c.getPrice()).sum());

        System.out.println("나이가 20살 이상인 사람만 고객 이름 정렬");
        list.stream().filter(c -> c.getAge() >= 20).map(c -> c.getName()).sorted().forEach(s -> System.out.println(s));
    }
}
profile
주니어 개발자 되고싶어요

0개의 댓글