[JAVA]_함수형 인터페이스

전희주·2023년 4월 23일
0

JAVA

목록 보기
16/24
post-thumbnail

리뷰

익명 클래스

lambda 표현식 (함수형 프로그래밍)

  • @FunctionalInterface
    • 메서드는 하나의 추상메서드만을 가져야 함.
  • 람다 표현식은 파라미터와 리턴값의 유무에 따라 다양한 형태가 존재
    • 파라미터, 리턴 유무에 따른 4가지 형태 존재
      • 파라미터가 없는 형태: () -> System.out.println("Hello, World!")
      • 파라미터가 있는 형태: (String name) -> System.out.println("Hello, " + name + "!")
      • 여러 개의 파라미터가 있는 형태: (int x, int y) -> x + y
      • 리턴값이 있는 형태: (int x, int y) -> { return x + y; }
  • 4가지 기능을 자바에서 API로 제공
    • java.util.function
      • java.util.function 패키지에서는 다양한 함수형 인터페이스를 제공

함수형 인터페이스 개념

  • 함수형 인터페이스 O/X 출제 예정
    • 인터페이스 별 리턴 타입이랑 파라미터 개수 기억
  • ✨ 함수형 인터페이스 실습 예제 중요
  • 메서드 참조 표현식
  • 스트림
  • Predicate 빈칸 채우기
  • 람다 표현식을 많이 기억하기 (암기)
  • 메서드 참조 표현식에서 :: 쓰면 자료형만 기재 가능

✨ (암기)

실습 코드 분석

ConsumerTest

  • 파라미터 있고 리턴 없음
  • Consumer<T> : 인자만 있고 반환값이 없는 인터페이스

  • Consumer

    • Consumer 인터페이스는 T 타입의 인자를 받아서 소비하는 accept 메서드를 제공합니다. 해당 예제에서는 익명 클래스와 lambda 표현식을 사용하여 Consumer 객체를 생성하고 accept 메서드를 호출하는 방법을 보여줍니다.

		// java.util.function.Consumer 인터페이스
		/*
		 *   Consumer<T> :  void accept(T t)  : T를 파라미터로 받아서 소비
		 *  BiConsumer<T,U>:  void accept(T t, U u), T와 U를 파라미터로 받아서 소비
		 *  DoubleConsumer:  void accept(double d) : double를 파라미터로 받아서 소비
		 *  IntConsumer:  void accept(int d) : int를 파라미터로 받아서 소비
		 *  LongConsumer:  void accept(long d) : long를 파라미터로 받아서 소비
		 *  ObjDoubleConsumer<T> :  void accept(T t, double)  : T와 double를 파라미터로 받아서 소비
		 *  ObjIntConsumer<T> :  void accept(T t, int)  : T와 int를 파라미터로 받아서 소비
		 *  ObjLongConsumer<T> :  void accept(T t, long)  : T와 long를 파라미터로 받아서 소비
		 */
         
		//1. Consumer
		//익명 클래스
		Consumer<String> c = new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println("Consumer:" + t);
			}
		};
		c.accept("hello");
		
		//lambda 표현식
		Consumer<String> c2 = t -> {
			System.out.println("Consumer_lambda:" + t);			
		};
		c2.accept("hello2");
  • BiConsumer<T,U>: void accept(T t, U u)
    • BiConsumer 인터페이스는 두 개의 인자를 받아서 소비하는 accept 메서드를 제공합니다. 해당 예제에서는 익명 클래스와 lambda 표현식을 사용하여 BiConsumer 객체를 생성하고 accept 메서드를 호출하는 방법을 보여줍니다.
	//2. BiConsumer
		BiConsumer<String, String> b = new BiConsumer<String, String>() {
			
			@Override
			public void accept(String t, String u) {
				System.out.println("BiConsumer:"+ t +":" + u);
			}
		};
		
		BiConsumer<String, String> b2 = 
				(t, u) ->System.out.println("BiConsumer_lambda:"+ t +":" + u);

		b2.accept("hello", "world");
		
  • ObjIntConsumer<T> : void accept(T t, int)
  • ObjIntConsumer 인터페이스는 T 타입과 int 타입의 두 개의 인자를 받아서 소비하는 accept 메서드를 제공합니다. 해당 예제에서는 lambda 표현식을 사용하여 ObjIntConsumer 객체를 생성하고 accept 메서드를 호출하는 방법을 보여줍니다.
//3. ObjIntConsumer
		ObjIntConsumer<String> x = (s, i)->System.out.println(s+"\t"+i);
		x.accept("hello", 10);

FunctionTest

  • 파라미터 있고 리턴 존재
// java.util.function.Function 인터페이스 : 파라미터 있고 리턴 존재
		/*
           Function<T, R> :  R apply(T t)  ,  T를 R로 매핑
           BiFunction<T,U, R> :  R apply(T t, U u), T와 U를 R로 매핑
		   DoubleFunction<R> :   R apply(double) , double를 R로 매핑
		   IntFunction<R> :   R apply(int) , int를 R로 매핑
		   LongFunction<R> :   R apply(long) , long를 R로 매핑
		   LongToDoubleFunction :  double applyAsDouble(long value),long를 double로 매핑 
		   IntToDoubleFunction :  double applyAsDouble(int value), int를 double로 매핑
		   
		   ...
        */
  • Function, BiFunction, IntToDoubleFunction 등은 각각 파라미터로 받는 데이터 타입에 따라 R로 매핑해주는 인터페이스입니다.

  • 이를 활용하면 일반적인 객체 지향 프로그래밍의 메소드처럼, 파라미터를 받아 결과값을 리턴하는 함수를 만들 수 있습니다.

  • 이 코드에서는 각각의 함수형 인터페이스에 대해 익명클래스와 람다 표현식으로 구현하는 방법을 보여줍니다. 이를 통해 코드를 간결하게 만들 수 있고, 가독성을 높일 수 있습니다.

  • Function 인터페이스를 활용한 예시로는, 문자열의 길이를 구하는 코드

//1. Function<T, R>
		// 익명클래스
		Function<String, Integer> f = new Function<String, Integer>() {
			@Override
			public Integer apply(String t) {
				return t.length();
			}
		};
		System.out.println(f.apply("hello"));
		// lambda 표현식
		Function<String, Integer> f2 = t -> t.length();
		System.out.println(f2.apply("helloworld"));
  • BiFunction 인터페이스를 활용해 두 개의 문자열을 합쳐 그 길이를 구하는 코드
	// BiFunction
		BiFunction<String, String, Integer> x = new BiFunction<String, String, Integer>() {
			@Override
			public Integer apply(String t, String u) {
				return (t+u).length();
			}
		};
		
		BiFunction<String, String, Integer> x2 = (t, u)-> (t+u).length();		
		System.out.println(x2.apply("hello", "world"));
		
  • IntToDoubleFunction 인터페이스를 활용하는 코드로는, 정수를 실수로 변환하는 코드가 있습니다.
// IntToDoubleFunction
		IntToDoubleFunction y = new IntToDoubleFunction() {
			@Override
			public double applyAsDouble(int value) {
				return value + 0.0;
			}
		};
		
		IntToDoubleFunction y2 = v -> v+ 0.0;
		System.out.println(y2.applyAsDouble(100));

OperatorTest

  • 파라미터 있고 리턴 존재
// java.util.function.Operator 인터페이스 : 파라미터 있고 리턴 존재
		//  Operator와 Function과는 상속관계
		/*
           BinaryOperator<T> : BiFunction<T,T,T> 동일, 
                               T apply(T, T) 
                               
           DoubleBinaryOperator: double applyAsDouble(double left, double right)                     
           IntBinaryOperator: int applyAsInt(int left, int right)                     
           LongBinaryOperator: long applyAsLong(long left, long right)                     

           UnaryOperator<T> : Function<T,T> 동일
                              T apply(T)  
           DoubleUnaryOperator: double applyAsDouble(double left, double right                     
           IntUnaryOperator: int applyAsInt(int left)                     
           LongUnaryOperator: long applyAsLong(long left)                     

	    */
  • BinaryOperator 예제
  • BinaryOperator 인터페이스를 사용하는 예제입니다.
    • 익명 클래스와 람다 표현식을 사용하여 두 개의 Integer 값을 받아서 더한 값을 반환하는 객체를 생성하고, 이 객체를 사용하여 10과 20을 더한 값을 출력합니다.
// 익명 클래스
BinaryOperator<Integer> x = new BinaryOperator<Integer>() {
  @Override
  public Integer apply(Integer t, Integer u) {
    return t+u;
  }
};

// lambda 표현식
BinaryOperator<Integer> x2 = (t, u) -> t+u;
System.out.println(x2.apply(10, 20));
  • IntBinaryOperator 예제
    • IntBinaryOperator 인터페이스를 사용하는 예제입니다. 두 개의 int 값을 받아서 더한 값을 반환하는 객체를 생성하고, 이 객체를 사용하여 10과 20을 더한 값을 출력합니다.
IntBinaryOperator y = (n, n2)-> n+n2;
System.out.println(y.applyAsInt(10, 20));
  • UnaryOperator 예제
    • UnaryOperator<T> : Function<T,T> 동일
    • UnaryOperator는 하나의 인자를 받아서 같은 타입으로 리턴하는 함수적 인터페이스입니다. 따라서 UnaryOperator는 Function과 매우 유사합니다.
// UnaryOperator<T>
		UnaryOperator<Integer> k = new UnaryOperator<Integer>() {
			@Override
			public Integer apply(Integer t) {
				return t + 100;
			}
		};
		
		UnaryOperator<Integer> k2 = t -> t+100;
		System.out.println(k2.apply(100));
		
  • UnaryOperator를 사용하여 인자로 정수를 받아들이고 100을 더해 같은 타입으로 반환하는 k와 k2 변수가 선언됩니다.

  • k 변수는 익명 클래스를 사용하여 UnaryOperator 인터페이스를 구현하며, apply() 메서드에서는 정수를 받아들인 후 100을 더한 값을 반환합니다.

  • k2 변수는 람다 표현식을 사용하여 UnaryOperator 인터페이스를 구현합니다. t를 인자로 받아들인 후 100을 더한 값을 반환합니다.

  • IntUnaryOperator 예제
// IntUnaryOperator
		IntUnaryOperator z = new IntUnaryOperator() {
			@Override
			public int applyAsInt(int x) {
				return x+100;
			}
		};
  
  IntUnaryOperator z2 = t -> t+100;
		System.out.println(z2.applyAsInt(100));
  • IntUnaryOperator를 사용하여 인자로 정수를 받아들이고 100을 더해 정수 타입으로 반환하는 z와 z2 변수가 선언됩니다.

  • z 변수는 익명 클래스를 사용하여 IntUnaryOperator 인터페이스를 구현합니다. applyAsInt() 메서드에서는 정수를 받아들인 후 100을 더한 값을 반환합니다.

  • z2 변수는 람다 표현식을 사용하여 IntUnaryOperator 인터페이스를 구현합니다. t를 인자로 받아들인 후 100을 더한 값을 반환합니다.

PredicateTest

  • 파라미터 있고 리턴 존재(반드시 boolean)
  • Predicate는 하나의 인자를 받아서 boolean 값을 반환하는 함수를 나타낸다.
// java.util.function.Predicate 인터페이스 : 파라미터 있고 리턴 존재(반드시 boolean)
		/*
		   Predicate<T> :   boolean test(T t)
		   
		   DoublePredicate : boolean test(double t)
		   IntPredicate : boolean test(int t)
		   LongPredicate : boolean test(long t)

           BiPredicate<T,U> : boolean test(T t, U u )

	   */
  • Predicate<T> 인터페이스
	//Predicate<T>
		Predicate<String> x = new Predicate<String>() {
			@Override
			public boolean test(String t) {
				return t.length() == 5;
			}
		};
		// lambda 표현식
		Predicate<String> x2 = t -> t.length() == 5;
		System.out.println(x2.test("hello"));
  • 문자열을 입력으로 받아서 문자열 길이가 5인지 여부를 반환하는 Predicate 객체를 생성하는 코드와, 람다 표현식을 사용한 코드가 있다.
    • 람다 표현식에서는 입력으로 받은 문자열의 길이가 5와 같으면 true를 반환하고, 그렇지 않으면 false를 반환한다.

  • IntPredicate 인터페이스
//IntPredicate
		IntPredicate y = new IntPredicate() {
			@Override
			public boolean test(int value) {
				return value > 10;
			}
		}; 
		
		IntPredicate y2 = t -> t > 10;
		System.out.println(y2.test(5));
  • 이 인터페이스는 int 값을 입력으로 받아서 boolean 값을 반환하는 함수를 나타낸다. 코드에서는 숫자를 입력으로 받아서 10보다 큰지 여부를 반환하는 IntPredicate 객체를 생성하는 코드와, 람다 표현식을 사용한 코드가 있다.
    • 람다 표현식에서는 입력으로 받은 숫자가 10보다 크면 true를 반환하고, 그렇지 않으면 false를 반환한다.
  • BiPredicate<T, U> 인터페이스
//BiPredicate<T, U>
		BiPredicate<String, Integer> k  = new BiPredicate<String, Integer>() {
			@Override
			public boolean test(String t, Integer u) {
				return t.length() == u;
			}
		};
		
		
		BiPredicate<String, Integer> k2 = (t, u) ->t.length() == u;
		System.out.println(k2.test("hello", 5));
  • 두 개의 인자를 받아서 boolean 값을 반환하는 함수를 나타낸다. 코드에서는 문자열과 숫자를 입력으로 받아서 문자열의 길이와 숫자가 같은지 여부를 반환하는 BiPredicate 객체를 생성하는 코드와, 람다 표현식을 사용한 코드가 있다.
    • 람다 표현식에서는 입력으로 받은 문자열의 길이와 숫자가 같으면 true를 반환하고, 그렇지 않으면 false를 반환한다.

SupplierTest

  • 파라미터 없고 리턴 존재
  • Supplier 인터페이스는 파라미터가 없고 리턴값이 존재하는 함수형 인터페이스입니다.
  • 이를 이용하여 인스턴스 생성 시 필요한 값을 동적으로 제공하는 경우 유용합니다.
// java.util.function.Supplier 인터페이스 : 파라미터 없고 리턴 존재
		/*
		   Supplier<T> : T get(),  T 타입 리턴
		   BooleanSupplier :  boolean getAsBoolean() : boolean 타입 리턴
		   DoubleSupplier :  double getAsDouble() : double 타입 리턴
		   IntSupplier :  int getAsInt() : int 타입 리턴
		   LongSupplier :  long getAsLong() : long 타입 리턴
		
		*/
  • Supplier<T> 예제
//1. Supplier<T>
		// 익명 클래스
		Supplier<String> s = new Supplier<String>() {
			@Override
			public String get() {
				return "hello";
			}
		};
		System.out.println(s.get());
		
		// lambda 표현식 
		Supplier<String> s2 = ()-> "hello2";
		System.out.println(s2.get());
  • 익명 클래스와 람다식을 사용하여 Supplier 인스턴스를 생성합니다. 이 인스턴스는 "hello" 문자열을 리턴하는 get() 메소드를 구현합니다. 그리고 이를 출력하여 "hello"가 출력됩니다.
  • IntSupplier 인터페이스 예제
//IntSupplier
		// 익명클래스
		IntSupplier x  = new IntSupplier() {
			@Override
			public int getAsInt() {
				return 100;
			}
		};
		System.out.println(x.getAsInt());
		// lambda 표현식
		IntSupplier x2 = ()-> 100;
		System.out.println(x2.getAsInt());
		
  • IntSupplier 인터페이스는 파라미터가 없고 int형 값을 리턴하는 함수형 인터페이스입니다.
    • 이를 이용하여 인스턴스 생성 시 동적으로 int형 값을 제공하는 경우 유용합니다.
    • 익명 클래스와 람다식을 사용하여 IntSupplier 인스턴스를 생성합니다. 이 인스턴스는 100이라는 int형 값을 리턴하는 getAsInt() 메소드를 구현합니다. 그리고 이를 출력하여 100이 출력됩니다.
    • 코드 실행 중에 현재 시간, 사용자 입력 등을 계산하여 값을 제공하는 것이 동적으로 값을 제공하는 것
    • 메서드를 호출하는 시점에 최초 1회 값이 생성되고, 그 이후에는 이전에 생성된 값을 반환

메서드 참조 표현식

  • 메서드 참조(Method Reference)는 람다식이 하나의 메서드만 호출하는 경우 해당 메서드의 이름을 사용하여 람다식을 간결하게 만드는 것
  • UnaryOperator<Integer> p3 = Calculator::methodA2; // 중요
  • UnaryOperator<String> yy3 = String::toUpperCase; // 중요
  • Consumer<String> m3 = System.out::println; // 중요
package p02;

import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.UnaryOperator;

class Calculator{
	//static 메서드
	public static int methodA(int x , int y) {
		return x + y;
	}
	public static int methodA2(int x) {
		return x;
	}
	// 인스턴스 메서드
	public int methodB(int x, int y) {
		return x + y;
	}
}
public class MethodReference {
	public static void main(String[] args) {
		//static 메서드
		BinaryOperator<Integer> k = new BinaryOperator<Integer>() {
			@Override
			public Integer apply(Integer t, Integer u) {
				return Calculator.methodA(t, u);
			}
		};
		
		BinaryOperator<Integer> k2 = (t, u) -> Calculator.methodA(t, u);
		BinaryOperator<Integer> k3 = Calculator::methodA;
		
		System.out.println(k.apply(10, 20));
		System.out.println(k2.apply(10, 20));
		System.out.println(k3.apply(10, 20));
		
		//
		Function<String, Integer> z = new Function<String, Integer>() {
			@Override
			public Integer apply(String t) {
				return Integer.parseInt(t);
			}
		};
		Function<String, Integer> z2 = t -> Integer.parseInt(t);
		Function<String, Integer> z3 = Integer::parseInt;
		System.out.println(z.apply("10") + 10);
		System.out.println(z2.apply("10") + 10);
		System.out.println(z3.apply("10") + 10);
		
		//UnaryOperator
		UnaryOperator<Integer> p = new UnaryOperator<Integer>() {
			@Override
			public Integer apply(Integer t) {
				return Calculator.methodA2(t);
			}
		};
		
		UnaryOperator<Integer> p2 = t -> Calculator.methodA2(t);
		UnaryOperator<Integer> p3 = Calculator::methodA2; // 중요
		
		System.out.println(p.apply(100));
		System.out.println(p2.apply(100));
		System.out.println(p3.apply(100));
		
		//#######################################
		// 인스턴스 메서드
		Calculator c = new Calculator();
		
		BinaryOperator<Integer> xx = new BinaryOperator<Integer>() {
			@Override
			public Integer apply(Integer t, Integer u) {
				return c.methodB(t, u);
			}
		};
		
		BinaryOperator<Integer> xx2 = (t, u)-> c.methodB(t, u);
		BinaryOperator<Integer> xx3 = c::methodB;
		System.out.println(xx.apply(10, 20));
		System.out.println(xx2.apply(10, 20));
		System.out.println(xx3.apply(10, 20));
		// String 의 메서드 : 인스턴스 메서드
		/*
		 *   String s = "hello";
		 *   s.lenght();
		 *   s.인스턴스메서드();
		 *   
		 */
		UnaryOperator<String> yy = new UnaryOperator<String>() {
			@Override
			public String apply(String t) {
				return t.toUpperCase();
			}
		};
		UnaryOperator<String> yy2 = t -> t.toUpperCase();
		UnaryOperator<String> yy3 = String::toUpperCase; // 중요
		
		System.out.println(yy.apply("hEllO"));
		System.out.println(yy2.apply("hEllO"));
		System.out.println(yy3.apply("hEllO"));
      		
		// System.out.println
		Consumer<String> m = new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println(t);
			}
		};
		
		Consumer<String> m2 = t -> System.out.println(t);
		Consumer<String> m3 = System.out::println;  // 중요
		
		m.accept("AAA");
		m2.accept("AAA");
		m3.accept("AAA");
		
		
	}//end main
}//end class

스트림

  • Stream API를 사용하여 배열과 컬렉션에서 Stream을 얻고 사용
  • 스트림은 함수형 프로그래밍을 지원하는 Java 8에서 새로 추가된 기능으로, 배열이나 컬렉션의 요소를 처리하기 위한 작업을 지연 실행할 수 있으며, 병렬 처리도 지원합니다. 따라서, 이전에는 for문과 같은 반복문을 사용하여 처리하던 작업을 스트림으로 대체하여 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.
  • 배열에서 Stream을 얻는 방법
    • Arrays.stream() 메서드를 사용하여 배열을 스트림으로 변환합니다.
    • 그리고 변환된 스트림을 forEach() 메서드를 사용하여 출력합니다.
    • 람다식을 이용하여 출력할 수 있으며, Consumer 함수형 인터페이스를 이용해서도 출력할 수 있습니다.
		//1. 배열에서 Stream 얻기
		String [] names = {"홍길동","이순신","유관순"};
		Stream<String> stream =   Arrays.stream(names);
		
		Consumer<String> consumer = new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println(t);
			}
		};
		Consumer<String> consumer2 = t-> System.out.println(t);
		Consumer<String> consumer3 = System.out::println;
		
//		stream.forEach(consumer2);
//		stream.forEach(t-> System.out.println(t));
//		stream.forEach(consumer3);
		stream.forEach(System.out::println);
		
  • 컬렉션에서 Stream을 얻는 방법
    • List 인터페이스에서 제공하는 stream() 메서드를 사용하여 컬렉션을 스트림으로 변환합니다.
    • 그리고 변환된 스트림을 forEach() 메서드를 사용하여 출력합니다.
    • 중요

      stream.filter(xxx2).forEach(System.out::println);

//2. 컬렉션에서 stream 얻기
		List<String> list = Arrays.asList("홍길동1","이순신1","유관순1");
		
		Stream<String> stream2 = list.stream();
		stream2.forEach(System.out::println);
package p03;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class StreamTest2 {

	public static void main(String[] args) {
		
	
		// 2. 컬렉션에서 stream 얻기 
		List<String> list = Arrays.asList("홍길동","이순신", "유관순", "이순신"); 
		Stream<String> stream = list.stream(); 
		
		// 중간 처리 1 - 중복 제거 
		stream.distinct().forEach(System.out::println);
		
		// 중간 처리 2 - 필터링 
		stream = list.stream(); 
		Predicate<String> xxx = new Predicate<String>() {
			
			@Override
			public boolean test(String t) {
				return t.startsWith("이"); 
			}
		};
		Predicate<String> xxx2 = t->t.startsWith("이"); 
		System.out.println();
		stream.filter(xxx2).forEach(System.out::println); // 중요 
	}

}

StreamTest3

package p03;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamTest3 {

	public static void main(String[] args) {

	
		// 리스트(List)를 생성
		// 이 리스트에는 1, 2, 3, 4, 5의 정수값이 저장
	    List<Integer> xyz = Arrays.asList(1,2,3,4,5);
	  
	    // 최종처리: sum(), count(), max(), min(), average()
	    
	    // 스트림(Stream)을 생성
	    // 생성한 스트림을 이용하여 최종처리 메서드인 sum(), count(), max(), min(), average()를 호출
	    // 이 코드에서는 count() 메서드를 사용하여 리스트(List)의 원소 개수를 구합니다.
	    Stream<Integer> stream = xyz.stream();
	    long count = stream.count();
	    System.out.println("갯수1:" + count);
	    System.out.println("갯수2:" + xyz.stream().count());
	    
	    
	    
	    
	    
	    //실습: 짝수값의 갯수 출력하시오.
	    Stream<Integer> stream2 = xyz.stream();
	    // 스트림을 이용하여 filter() 메서드를 호출하여 조건에 맞는 값을 추출
	    //////////////////////////////////////////////////
	    Predicate<Integer> abc = new Predicate<Integer>() {
			@Override
			public boolean test(Integer t) {
				return t%2==0;
			}
		};
		Predicate<Integer> abc2 = t-> t%2==0;
		// 리스트(List)에서 짝수값의 갯수를 구합니다.
		System.out.println(stream2.filter(abc2).count());
		//////////////////////////////////////////////////
//		System.out.println(stream2.filter(t-> t%2==0).count());
	    ///////////////////////////////////////////////////////////
		
		
		
		
		// 스트림의 요소를 int나 double 타입으로 변경하여 처리하는 경우
		// 이 때는 mapToInt()나 mapToDouble() 메서드를 사용
		List<Integer> xyz2 = Arrays.asList(1,2,3,4,5);
		Stream<Integer> kkk2 = xyz2.stream();  
		// sum()등 집계메서드가 없다. --> IntStream, DoubleStream 등으로 변경 필요
		///////////////////////////////////////////////////////////
		ToIntFunction<Integer> bbb = new ToIntFunction<Integer>() {
			@Override
			public int applyAsInt(Integer value) {
				return value;
			}
		};
		ToIntFunction<Integer> bbb2 = v->v;
		////////////////////////////////////////////////
		IntStream kkk3 = kkk2.mapToInt(v -> v);	
		
		// IntStream으로 변경된 스트림은 sum() 메서드를 사용하여 총합을 구할 수 있습니다.
		System.out.println("총합1:" + kkk3.sum());
		
		
		
		// 배열(Array)을 IntStream으로 변경하여 처리하는 경우
		// 배열은 바로 IntStream 얻을 수 있다.
		int [] ccc = {1,2,3};
		IntStream ccc2 =  Arrays.stream(ccc);
		int sum = ccc2.sum();
		System.out.println("총합2:" + sum);
		
		/////////////////////////////////////////
		
		List<Integer> xyz5 = Arrays.asList();
		Stream<Integer> kkk5 = xyz5.stream();  
		IntStream ttt = kkk5.mapToInt(v->v);
		
		OptionalDouble optDouble = ttt.average(); 
		// Optional 타입은 값이 없을경우 예외가 발생되는데, 예외방지가능(기본값설정)
		System.out.println("평균값1:" +  optDouble.orElse(0.0)); // OptionalDouble[3.0]
		double value = optDouble.orElse(0.0); // 권장
//		double value2= optDouble.getAsDouble(); //권장안함
 		System.out.println("평균값2:" +  value); // 3.0
		
 		/////////////////////////////////////////
		List<Integer> xyz6 = Arrays.asList(1,2,3,4,5);
		Stream<Integer> kkk6 = xyz6.stream();  
		IntStream ttt2 = kkk6.mapToInt(v->v);
		
		OptionalInt optInt = ttt2.max(); // ttt2.min()
		int value3 = optInt.orElse(0);
		System.out.println("최대(소)값:" + value3);
		
		
		
		
	}//end main
}//end class







StreamTest4

package p03;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamTest4 {

	public static void main(String[] args) {

	
		String [] names = {"홍길동","세종","을지문덕", "이순신"};
		
		/*
		 * 최종처리: List, Set, Map 반환받기
		 * .collect(Collectors.toList());
		 * .collect(Collectors.toSet());
		 * .collect(Collectors.toMap(key, value));
		 */
		
		// 이름이 3글자 이상인 데이터를 List로 반환받기
		List<String> list = Arrays.stream(names)
		                  .filter(n->n.length()>2)
		                  .collect(Collectors.toList()); // 이름이 3글자 이상인 데이터를 List로 반환
		System.out.println(list); // ["홍길동", "을지문덕", "이순신"]
		
		// 이름 글자수 set로 반환받기 ( 순서없고 중복불가 )
		Set<Integer> set = Arrays.stream(names)
		                 .map(n->n.length())
		                 .collect(Collectors.toSet()); // 이름 글자수 set로 반환받기
		System.out.println(set); // [2, 3, 4]
		
		// 이름과 글자수를 쌍(Map)으로 반환받기
		Map<String, Integer> map = Arrays.stream(names)
		                         .collect(Collectors.toMap(v->v, v->v.length())); // 이름과 글자수를 쌍(Map)으로 반환받기
		System.out.println(map); // {홍길동=3, 이순신=3, 을지문덕=4, 세종=2}
	}
}

0개의 댓글