- 메서드 참조 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
예제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 |