[Java]함수형 인터페이스와 스트림, Stream

수경·2023년 8월 30일
0

함수형 인터페이스, Functional Interface

  • 추상 메소드를 딱 하나만 가지고 있는 인터페이스
  • @FunctionalInterface : 어노테이션을 달아두면 함수형 인터페이스라는 것을 표시할 수 있다.
  • JDK가 제공하는 함수

1. Consumer > 매개변수o, 반환값x

  • 매개변수를 받아서 소비하는 업무를 구현한다.

  • acceptXXX() 추상 메소드 제공한다.

  • 종류

    • Consumer<T>
    • Biconsumer<T>
    • IntConsumer
  • 예제 코드

Consumer<Integer> c1 = num -> System.out.println(num*num);
c1.accept(10);
		
Consumer<String> c2 = str -> System.out.println(str.length());
c2.accept("문자열");

2. Supplier > 매개변수x, 반환값o

  • 매개변수 없이 반환값을 돌려주는 업무를 구현

  • getXXX() 추상 메소드 제공

  • 종류
    - Supplier<T>

  • 예제 코드

Supplier<Integer> s1 = () -> 100;
System.out.println(s1.get());

Supplier<String> s3 = () -> "홍길동";
System.out.println(s3.get());

3. Function > 매개변수o, 반환값o

  • 매개변수를 전달하면 처리 후, 반환값을 돌려주는 업무를 구현

  • applyXXX() 추상 메소드 제공

  • 종류

    • Function<T,R> : T 자료형을 매개변수로 받아 R 자료형을 반환한다.
    • BiFunction<T,U,R> : T,U 자료형을 매개변수로 받아 R 자료형을 반환한다.
  • 예제 코드

Function<Integer, Boolean> f1 = num -> num>0;
System.out.println(f1.apply(-10));

BiFunction<Integer, Integer, Integer> bf1 = (a,b) -> a+b;
System.out.println(bf1.apply(10, 20));

DoubleToIntFunction f4 = num -> (int)num;
System.out.println(f4.applyAsInt(3.14));

false
30
3

4. Operator > 매개변수o, 반환값o

  • 매개변수를 전달하면 처리 후, 반환값을 돌려주는 업무를 구현

  • applyXXX() 추상 메소드 제공

  • Function의 하위셋 : 특정 역할만 하도록 특화시킨 인터페이스

  • 매개변수와 반환값의 타입이 같다.

  • 종류
    - BinaryOperator<t>

  • 예제 코드

//1. BiFunction
BiFunction<Integer, Integer, Integer> bf1 = (a,b) -> a+b;

//2. BinaryOperator
BinaryOperator<Integer> bo1 = (a,b) -> a+b;
System.out.println(bo1.apply(10, 20));

30

5. Predicate > 매개변수o, 반환값o

  • 매개변수를 전달하면 처리 후, 반환값을 돌려주는 업무를 구현

  • applyXXX() 추상 메소드 제공

  • 매개변수를 전달받아, Boolean 반환

  • Function 하위셋

  • 종류
    - Predicate<T>

  • 예제 코드

//1. Function
Function<Integer, Boolean> f1 = num -> num>0;

//2. Predicate
Predicate<Integer> p1 = num -> num>0;
System.out.println(p1.test(10));

//3. Predicate
BiPredicate<Integer, Integer> bp2 = (a,b) -> a>b;
System.out.println(bp2.test(10, 20));
System.out.println(bp2.test(20, 10));

false
false
true

요약

1. Consumer

  • (매개변수) -> {구현부}

2. Supplier

  • () -> {return 값}

3. Function

  • (매개변수) -> {return 값}

4. Operator

  • (매개변수) -> {return 값}
  • 매개변수와 반환값의 자료형이 동일

5. Predicate

  • (매개변수) -> {return 값}
  • 반환값이 무조건 boolean

스트림

배열, 컬렉션 탐색하는 방법

  1. for문(루프변수)
  2. 향상된 for문
  3. Iterator
    4. 스트림
  • 자바 8부터 도입된 기능으로, 데이터의 처리를 보다 간결하고 효율적으로 할 수 있게 해주는 도구
  • 데이터 소스로부터 탐색/조작 가능한 도구
  • list.stream().forEach()

스트림을 얻어오는 방법

//1. 순수배열로부터
int[] nums1 = {10,20,30,40};
		
Arrays.stream(nums1).forEach(num -> System.out.println(num));
		
//2. 컬렉션으로부터
ArrayList<Integer> num2 = new ArrayList<Integer>();
num2.add(100);
num2.add(200);
num2.add(300);
		
num2.stream().forEach(num -> System.out.println(num));

//3. 숫자범위로부터
//Stream<Integer> : 범용 스트림 > forEach > Consumer<Integer>
//IntStream		  : 전용 스트림 > forEach > IntConsumer
		
IntStream
	.range(1, 10)	//1~9
	.forEach(num -> System.out.print(num));

데이터 처리 파이프

1. 중간 파이프

  • 반환값 o + 스트림 반환
  • T/F로 판단하므로 Predicate가 제일 적합하다.
  • 종류
    - filter() : 필터링
    - distinct() : 중복 제거
    - map(), mapXXX() : 변환 작업
    - sorted() : 정렬

2. 최종 파이프

  • 반환값 x + void
  • 반환값 0 + 다른 자료형 반환
  • 활용도가 제일 높다.
  • 요소를 받아 제일 마지막 처리를 하므로 Consumer가 제일 적합하다.
  • 종류
    • forEach() : 요소처리
    • allMatch() : 모든 요소가 조건을 100% 만족
    • anyMatch() : 일부 요소가 조건을 만족
    • noneMatch() : 모든 요소가 조건을 불만족
    • count(), max(), min(), sum(), average()

filter()

//짝수만 출력
list.stream().filter(num -> num % 2 ==0).forEach(num -> {
	System.out.printf("%-4d", num);
});

//체중 70kg 이상인 여성 출력
Data.getUserList().stream()
		.filter(user -> user.getWeight() >= 70)
		.filter(user -> user.getGender() == 2)
		.forEach(user -> System.out.print(user + " "));

distinct()

//중복된 이름 제거
String[] names = {"홍길동", "아무개","이순신","권율","강감찬","연개소문","홍길동","이순신", "남궁장군","연개소문"};
Arrays.stream(names)
	.distinct()
	.filter(str -> str.length() == 3)
	.forEach(str -> System.out.println(str));

map()

//names에서 이름만 추출
String[] names = {"홍길동", "아무개","이순신","권율","강감찬","연개소문","홍길동","이순신", "남궁장군","연개소문"};
		
Arrays.stream(names)
	.map(name -> name.substring(1))
	.forEach(name -> System.out.println(name));

sorted()

  • 배열/컬렉션의 sort()와 사용법이 동일하다 > Comparator 구현
//오름차순
Data.getIntList(10)
	.stream()
	.sorted()
	.forEach(n-> System.out.println(n));
		
//내림차순
Data.getIntList(10)
	stream()
	sorted((a,b) -> b-a)
	forEach(n-> System.out.println(n));

allMatch(), anyMatch(), noneMatch()

  • 스트림 요소들이 제시한 조건을 만족 유무 판단
    a. boolean allMatch(Predicate) : 모든 요소가 조건을 100% 만족
    b. boolean anyMatch(Predicate) : 일부 요소가 조건을 만족
    c. boolean noneMatch(Predicate) : 모든 요소가 조건을 불만족
int[] nums = {2,2,34,4,50};

//배열에서 짝수만 들어있는지 체크
System.out.println(Arrays.stream(nums).allMatch(n-> n%2 == 0));		//true

if (Arrays.stream(nums).allMatch(n-> n%2 == 0)) {
	System.out.println("짝수 배열");
} else {
	System.out.println("홀수 발견");
}

System.out.println(Arrays.stream(nums).noneMatch(n-> n%2 == 0));	//모두가 짝수가 아닌지 체크

true
짝수 배열
false

count(), max(), min(), sum(), average()

System.out.println(Data.getIntList().stream().count());
System.out.println(Data.getIntList().stream().max((a,b)-> a-b));		//Optional[99]
System.out.println(Data.getIntList().stream().max((a,b)-> a-b).get());
System.out.println(Data.getIntList().stream().min((a,b)-> a-b).get());

//sum(), average() > 전용 메소드 통해 사용할 수 있다.
int sum = Data.getIntList().stream()
						.mapToInt(n-> n)	//Stream<Integer>(x) IntStream(o)
						.sum();
System.out.println(sum);
		
double avg = Data.getIntList().stream()
							.mapToDouble(n->n)
							.average().getAsDouble();
System.out.println(avg);

100
Optional[99]
99
0
4746
47.46

profile
웹백엔드개발자를 꿈꾸는

0개의 댓글