본문 바로가기
ICIA 수업일지

2021.07.16 수업일지

by 주성씨 2021. 7. 17.

- 메서드 참조 Review

- 람다식보다 짧게 사용할 수 있어서 사용
- 초보자들에게는 어려울수 있음

- Consumer<T> void accept(T t){ Collections.reverse(T t); }

예제1)

package ex1;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class ArrangeList1 {
	public static void main(String[] args) {
		List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
		ls = new ArrayList<>(ls);
		// reverse 메소드 호출 중심의 람다식 기반
		// 변수의 이름은 상관업다. 자료형이 중요하다.
		// Consumer<List<Integer>> c = l -> Collections.reverse(l);
		// l 인자는 뺄수 있다.
		// static 메소드 참조 기반
		// 클래스::인스턴스 클래스
		Consumer<List<Integer>> c = Collections::reverse;
		c.accept(ls); // ls는 그대로 reverse에 전달되고, 순서 뒤집기 진행.
		System.out.println(ls); // 9 7 5 3 1 출력
	}
}

 

1.2 인스턴스 메소드 참조1 : effectively final(사실상 상수)

예제2)

package ex1;

//import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

class JustSort {
	// ?(Object와 유사) = T 어떤 자료형이든 받을 수 있다.
	public void sort(List<?> lst) { // 인스턴스메소드
		Collections.reverse(lst);
	}
}

public class ArrangeList3 {
	public static void main(String[] args) {
		List<Integer> ls = Arrays.asList(1, 3, 5, 7, 9);
//		ls = new ArrayList<>(ls);
		JustSort js = new JustSort(); // js는 effectively final
		// final JustSort라고 하면 아래는 같이 에러가 난다.
		// js=new JustSort(); 에러
		// 인스턴스 영역이 다르기 때문이다.
//		Consumer<List<Integer>> c = e -> js.sort(e); // 람다식기반
		Consumer<List<Integer>> c = js::sort; // 인스턴스 메소드 참조 기반
		c.accept(ls);
		System.out.println(ls);
		// js=null; 에러
	}
}

 

예제3)

package ex1;

import java.util.Arrays;
import java.util.List;

public class ForEachDemo {
	public static void main(String[] args) {
		List<String> ls = Arrays.asList("Box", "Robot");
		// 굉장히 많이 사용하는 forEach문
		// this ; 현재 작업중인 인스턴스의 참조변수
		ls.forEach(s -> System.out.println(s)); // 람다식 기반
		ls.forEach(System.out::println); // 인스턴스 메소드 참조 기반
	}
}

 

예제4)

package ex1;

import java.util.function.ToIntBiFunction;

// 래퍼 클래스
// 인티저 클래스 가져다 쓰면 된다.
// 예시일뿐 참고하자.
class IBox {
	private int n;

	public IBox(int i) {
		n = i;
	}

	public int larger(IBox b) {
		if (n > b.n)
			return n;
		else
			return b.n;
	}
	
//	public int smaller(IBox b) {
//		if (n < b.n)
//			return b.n;
//		else
//			return n;
//	}
}
							// 변수 두게를 받아서 정수로 반환한다.
//ToIntBiFunction<T, U> int applyAsInt(T t, U u)
//규칙: t의 인스턴스 메소드 호출시 u를 파라미터(인자)로 사용한다.
public class NoObjectMethodRef {
	public static void main(String[] args) {
		IBox ib1 = new IBox(5);
		IBox ib2 = new IBox(7);
// 두 상자에 저장된 값 비교하여 더 큰 값 반환
		
		// 람다식 apply구현 기반
//		ToIntBiFunction<IBox, IBox> bf = (b1, b2) -> b1.larger(b2);
		
		// 인스턴스 메소드 참조 기반
		ToIntBiFunction<IBox, IBox> bf = IBox::larger;
		int bigNum = bf.applyAsInt(ib1, ib2);
		System.out.println(bigNum);
		
//		ToIntBiFunction<IBox, IBox> bf1 = IBox::smaller;
//		int smallNum = bf.applyAsInt(ib1, ib2);
//		System.out.println(smallNum);
	}
}

 

문제1 해보기

 

1.4 생성자 참조

- 람다식을 작성 시 인스턴스 생성 후 이의 참조 값을 반환하는 경우가 있다. 이 경우 메소드 참조 방식을 쓸 수 있음.

예제5)

package ex1;

import java.util.function.Function;

public class StringMaker {
	public static void main(String[] args) {
		
//Function<char[], String> f = ar -> { return new String(ar); };
//Function<char[], String> f = ar -> new String(ar);
		
		Function<char[], String> f = String::new; // 메소드 참조방식과 같음
		
// Function<T, R> R apply(T t)
//규칙: 입력(char[])를 사용하여 String 인스턴스를 리턴한다.
		
		char[] src = { 'R', 'o', 'b', 'o', 't' };
		String str = f.apply(src);
		System.out.println(str);
		
		char[] src1 = {'H', 'e', 'l', 'l', 'o'};
		String str1 = f.apply(src1);
		System.out.println(str1);
	}
}

 

문제2> 아래 예제가 잘 동작하도록 빈 문장 하나를 채워 넣자. 단 채워 넣을 문장은 BiFunction 인터페이스를 기반으로 작성된 <람다식>을 포함해야 한다.

문제3> 위 문제 1에서 요구한 내용의 구현 결과를 <메소드 참조> 기반으로 수정해보자

package ex2;

import java.util.function.BiFunction;

class Box<T, U> {
	private T id;
	private U con;

	public Box(T i, U c) {
		id = i;
		con = c;
	}

	public void showIt() {
		System.out.println("ID: " + id + ", " + "Contents: " + con);
	}
}

class BoxMaker {
	public static void main(String[] args) {
		// 채워 넣어야 할 문장, 참조변수 bf의 선언
		// 람다식
		BiFunction<Integer,String,Box<Integer, String>> bf = null; 
//		bf = (a,b) -> new Box<>(a,b);
		// 메소드 참조
		bf=Box::new;
		
		Box<Integer, String> b1 = bf.apply(1, "Toy");
		Box<Integer, String> b2 = bf.apply(2, "Robot");

		b1.showIt();
		b2.showIt();
	}
} // BiFunction<T, U, R> R apply(T t, U u)

 

- Stream

1. Stream의 이해

- 파이프는 연산입니다.
- 최종연산은 마지막에 연결하는 파이프이고, 중간연산은 중간에 연결하는 파이프이다.
- 중간연산 간에는 순서가 바뀌어도 된다.

예제1)

package streamEx;

import java.util.Arrays;
import java.util.stream.IntStream;

public class MyFirstStream {
	public static void main(String[] args) {
		int[] ar = { 1, 2, 3, 4, 5 };
		//Arrays ; 배열과 관련된 메서드를 가지고 있다.
//		IntStream stm1 = Arrays.stream(ar); // 스트림 생성
//		IntStream stm2 = stm1.filter(n -> n % 2 == 1); // 중간 파이프 구성
//		int sum = stm2.sum(); // 최종 파이프 구성
//		System.out.println(sum);
		
//		위와 같이 안하고 다음과 같이 해보도록 하자.
		int sum = Arrays.stream(ar).filter(n -> n % 2 == 0).sum();
		System.out.println(sum);
		
//		IntStream stm3 = Arrays.stream(ar); // 스트림 생성
//		IntStream stm4 = stm3.filter(n -> n % 2 != 1); // 중간 파이프 구성
//		int sum1 = stm4.sum(); // 최종 파이프 구성
//		System.out.println(sum1);
		
//		위와 같이 안하고 다음과 같이 해보도록 하자.
		int sum1=Arrays.stream(ar).filter(n->n%2==1).sum();
		System.out.println(sum1);
	}
}

 

2. 스트림 생성하기 : 배열

예제3)

package streamEx;

import java.util.Arrays;
import java.util.stream.Stream;

public class StringStream {
	public static void main(String[] args) {
		String[] names = { "CHA", "LEE", "PARK" };

//		Stream<String> stm = Arrays.stream(names); // 스트림생성
//		stm.forEach(s -> System.out.println(s)); // 최종연산진행
		// 체이닝 기법으로 간단히 코딩하시오..
		
		// 이와 같이 쓸 수 있다.
		Arrays.stream(names).forEach(s -> System.out.println(s));
		
		// 이와 같이도 쓸 수 있다.
		Arrays.stream(names).forEach(System.out::println);
	}
}

 

3. 스트림 생성하기 : Array 클래스의 배열 대상 다양한 메서드들

public static IntStream stream(int[] array)

public static IntStream stream(int[] array, int startInclusive, int endExclusive)

public static DoubleStream stream(double[] array)

public static DoubleStream stream(double[] array,int startInclusive,int endExclusive)

public static LongStream stream(double[] array)

public static LongStream stream(double[] array, int startInclusive, int endExclusive)

 

예제4)

package streamEx;

import java.util.Arrays;

public class DoubleStream {
	public static void main(String[] args) {
		double[] ds = { 1.1, 2.2, 3.3, 4.4, 5.5 };
		
		Arrays.stream(ds).forEach(d -> System.out.print(d + "\t"));
		System.out.println();
		// index 1부터 index 4미만 까지만 추출하겠다.
		Arrays.stream(ds, 1, 4).forEach(d -> System.out.print(d + "\t"));
		System.out.println();
	}
}

 

4. 스트림 생성하기 : 컬렉션 인스턴스

- 컬렉션 인스턴스를 대상으로 스트림 생성 시 호출하는 메소드

- default Stream stream()
  // java.util.Collection의 디폴트 메소드

 

예제5)

package streamEx;

import java.util.List;
import java.util.Arrays;

class ListStream {
	public static void main(String[] args) {
		List<String> list = Arrays.asList("Toy", "Robot", "Box");

		list.stream().forEach(s -> System.out.print(s + " "));
		System.out.println();
	}
}

 

5. 필터링

- 필터링: 스트림을 구성하는 데이터 중 일부를 조건에 따라 걸러내는 연산
Stream<T> filter(Predicate<? super T> predicate) // Stream<T>에 존재
 // Predicate<T> boolean test(T t)

 

예제6)

package streamEx;

import java.util.Arrays;
import java.util.List;

public class FilterStream {
	public static void main(String[] args) {
		int[] ar = { 1, 2, 3, 4, 5 };
		Arrays.stream(ar).filter(n -> n % 2 == 1) // 참(홀수)만 통과시켜 스트림을 새로 만든다.
				.forEach(n -> System.out.print(n + "\t"));
		System.out.println();
		
		List<String> sl = Arrays.asList("Toy", "Robot", "Box");
		sl.stream().filter(s -> s.length() == 3) // 참(길이가3)만 통과시켜 스트림 만듬
				.forEach(s -> System.out.print(s + "\t")); // 최종 연산
		System.out.println();
	}
}

 

6. 매핑 : 하나의 값을 다른 값으로 대응시키는 것을 말한다.

- 문자열 스트림 기반으로 숫자 스트림을 생성했다면 이것을 매핑이라고 한다.

※ 참고

https://m.blog.naver.com/icbanq/221727893563

 

[진법변환] 2진수,8진수,10진수,16진수 쉽게 변환하는 방법 알아보기!

안녕하세요~~! 오늘도 여러분들께 유익한 정보를 드리러 온 나도비 입니다 !! 오늘의 주제는 2진수,8진수,1...

blog.naver.com

 

예제7)

package streamEx;

import java.util.Arrays;
import java.util.List;

class MapToInt {
	public static void main(String[] args) {
		List<String> ls = Arrays.asList("Box", "Robot", "Simple");
		
		// 스트림 안에 있던 값을 map에 넣고 출력된 값을 Integer로 박싱 후 
		ls.stream().map(s -> s.length()).forEach(n -> System.out.print(n + " "));

		// 대문자로 출렭
		ls.stream().map(s -> s.toLowerCase()).forEach(n -> System.out.print(n + " "));

		// 박싱하지 않고 바로 Integer로 대응
		ls.stream().mapToInt(s -> s.length()).forEach(n -> System.out.print(n + " "));
		
		System.out.println();
	}
}

 

문제1> 아래의 코드에서 ‘문자열이 담긴 상자’를 담고 있는 컬렉션 인스턴스를 생성 하였다. 이를 대상으로 스트림을 생성하고, 이 스트림을 기반으로 문자열 스트림을 생성하는 매핑 연산을 진행해보자. 그리고 그 결과를 forEach 연산을 통해 출력해보자.

package streamEx;

import java.util.Arrays;
import java.util.List;

class Box<T> {
	private T ob;

	public Box(T o) {
		ob = o;
	}

	public T get() {
		return ob;
	}
}

class BoxToString {
	public static void main(String[] args) {
		List<Box<String>> ls = Arrays.asList(new Box<>("Robot"), new Box<>("Simple"));
		
		ls.stream().map(s -> s.get()).forEach(n -> System.out.print(n + "\t"));

		// 이 위치에서 스트림 생성 및 매핑 연산을 진행하는 코드작성
		// 결과 : Robot Simple
	}
}

 

문제2> 위 문제 1에서는 Box을 String으로 매핑하였다. 이번에는 Box 을 Integer로 매핑하도록 문제 1의 답안을 수정해보자. 이때 Integer는 상자에 담긴 문자열의 길이다.

class BoxToString {
	public static void main(String[] args) {
//		List<Box<String>> ls = Arrays.asList(new Box<>("Robot"), new Box<>("Simple"));
//		
//		ls.stream().map(s -> s.get()).forEach(n -> System.out.print(n + "\t"));

		// 이 위치에서 스트림 생성 및 매핑 연산을 진행하는 코드작성
		// 결과 : Robot Simple
		
		List<Box<String>> ls = Arrays.asList(new Box<>("Robot"), new Box<>("Simple"));
		
		ls.stream().map(s -> s.get().length()).forEach(n -> System.out.print(n + "\t"));
		// 결과 : 5 6
	}
}

ㄴ 중간 파이프는 몇개가 와도 좋다.

 

7. 매핑2 : 필터링 후 매칭의 예

예제8)

package streamEx;

import java.util.ArrayList;
import java.util.List;

class ToyPriceInfo {
	private String model;
	private int price;

	public ToyPriceInfo(String m, int p) {
		model = m;
		price = p;
	}

	public int getPrice() {
		return price;
	}
}

public class ToyStream {
	public static void main(String[] args) {
		
		List<ToyPriceInfo> ls = new ArrayList<>();
		
		ls.add(new ToyPriceInfo("GUN_LR_45", 200));
		ls.add(new ToyPriceInfo("TEDDY_BEAR_S_014", 350));
		ls.add(new ToyPriceInfo("CAR_TRANSFORM_VER_7719", 550));

		int sum = ls.stream().filter(p -> p.getPrice() < 500) // 참만 통과시켜 스트림구성
				.mapToInt(t -> t.getPrice()) // 가격만으로 스트림구성
				.sum(); // 최종연산

		System.out.println("sum = " + sum);
	}
}

 

<문제3> 예제8번의 ToyPriceInfo 클래스에 다음 메소드를 추가하자.

public String getModel() { return model; }

그리고 예제의 내용대로 스트림을 생성한 이후에 다음의 내용대로 필터링, 매핑을 하고 마지막에 결과로 남은 스트림의 내용을 forEach 연산을 통해 전부 출력하자.

- 필터링 조건 : model 이 참조하는 문자열의 길이가 10을 넘으면 해당 인스턴스 통과
- 매핑 방법 : ToyPriceInfo 인스턴스 -> String 인스턴스(모델명)

		ls.stream().filter(p -> p.getModel().length() > 10).
		map(s -> s.getModel()).forEach(n -> System.out.println(n));
//		map(s -> s.getModel()).forEach(System.out::println);
TEDDY_BEAR_S_014
CAR_TRANSFORM_VER_7719

 

		// 모델명과 가격둘다
		ls.stream().filter(p -> p.getModel().length() > 10).
		forEach(s -> System.out.println(s.getModel()+"의 가격은 "+s.getPrice()));
TEDDY_BEAR_S_014의 가격은 350
CAR_TRANSFORM_VER_7719의 가격은 550

ㄴ 중간연산은 빠져도 되지만 최종연산은 빠지면 안된다.

 

8. 리덕션과 reduce 메서드

- 리덕션(Reduction): 데이터를 축소하는 연산

- reduce의 첫 번째 전달 인자를 스트림의 첫 번째 데이터로 간주함에 주의!
T reduce(T identity, BinaryOperator<T> accumulator) // Stream<T>에 존재
 // BinaryOperator<T> T apply(T t1, T t2)

 

package streamEx;

import java.util.List;
import java.util.Arrays;
import java.util.function.BinaryOperator;

class ReduceStream {
	public static void main(String[] args) {
		List<String> ls = Arrays.asList("Box", "Simple", "Complex", "Robot");
		
		// 가장 길이가 긴 문자열 추출
		// 펑션계열이기 떄문에 
		BinaryOperator<String> lc = (s1, s2) -> {
			if (s1.length() > s2.length())
				return s1;
			else
				return s2;
		};

		String str = ls.stream().reduce("", lc); // 스트림 빈 경우 "" 반환
		// .reduce("PineApple", lc); 변경해 볼것
		System.out.println(str);
		
		// 가장 길이가 짧은 문자열 추출
		BinaryOperator<String> st = (s1, s2) -> {
			if (s1.length() > s2.length())
				return s2;
			else
				return s1;
		};
		// 배열에 엠티스트링이 들어가기 때문에 ""가 출력된다.
		// reduce의 첫 번째 전달 인자를 스트림의 첫 번째 데이터로 간주하기 때문에 그렇다.
		String str1 = ls.stream().reduce("", st); // 스트림 빈 경우 "" 반환
		// .reduce("PineApple", lc); 변경해 볼것
		System.out.println(str1);
	}
}

ㄴ 토너먼트 방식을 통해서 데이터를 줄여가는 방식이다.

 

9. 병렬 스트림
- 병렬 처리 : 하나의 작업을 둘 이상의 작업으로 나너어서 동시에 진행하는 것.
- 자바 언어 차원에서 병렬처리를 지원하기 때문에 병렬 작업 구성을 더 이상 신경쓰지 않아도 된다.
- 작업량이 많을 경우 신속하게 처리하고 싶을때 사용한다.
- 반대로 작업량이 적을 경우 적은 양을 나누기 때문에 처리 시간이 더 오래걸린다.
- CPU Core 다중 처리를 생각하면 이해하기 쉽다.

예제10)

package streamEx;

import java.util.List;
import java.util.Arrays;
import java.util.function.BinaryOperator;

class ReduceParallelStream {
	public static void main(String[] args) {
		List<String> ls = Arrays.asList("Box", "Simple", "Complex", "Robot");

		BinaryOperator<String> lc = (s1, s2) -> {
			if (s1.length() > s2.length())
				return s1;
			else
				return s2;
		};
		long start = System.currentTimeMillis();
		// parallel ; 둘 이상의 일이 아주 유사한, 병행하는
		String str = ls.parallelStream().reduce("", lc);
		long end = System.currentTimeMillis();
		System.out.println("쇼오시간 : "+(end-start)+"밀리초");
		System.out.println(str);
	}
}

 

문제4> 예제10번을 사전정렬(알파벳)순으로 비교하여 사전 맨 앞쪽에 나와야 할 문자열, 또는 사전 맨 뒤에 나와야 할 문자열을 반환하도록 작성하시오.

package streamEx;

import java.util.List;
import java.util.Arrays;
import java.util.function.BinaryOperator;

class ReduceParallelStream {
	public static void main(String[] args) {
		List<String> ls = Arrays.asList("Box", "Complex", "Zero", "Robot");

		BinaryOperator<String> lc = (s1, s2) -> {
			// 사전앞쪽 > 사전뒤쪽 이면 양의 수를 리턴
			if (s1.compareTo(s2) > 0)
				return s2;
			else
				return s1;
		};
		String str = ls.parallelStream().reduce("Apple", lc);
		System.out.println(str);
	}
}

 

- 시간과 날짜

2.LocalDate 클래스
3.LocalTime 클래스
4.LocalDateTime 클래스

 

- Optional클래스

 

- HTML -> VSC

'ICIA 수업일지' 카테고리의 다른 글

2021.07.20 수업일지  (0) 2021.07.24
2021.07.19 수업일지  (0) 2021.07.24
2021.07.15 수업일지  (0) 2021.07.17
2021.07.14 수업일지  (0) 2021.07.17
2021.07.13 수업일지  (0) 2021.07.17