// ArrayList vs LinkedList
// - List : List 인터페이스 사용(사용법 동일)
// - Array : 배열구조
// Linked : 링크구조
// HashMap vs TreeMap
// - Map : Map 인터페이스 사용(사용법 동일)
// - Hash : Hash알고리즘 사용
// - Tree : 이진트리 사용
// TreeMap
// 이진 트리 구조
// 자동 정렬(키), 범위 검색 용이
// 키만 이진 트리로 관리!
// 값은 리스트로 관리
TreeMap<String, String> map=new TreeMap<String, String>();
map.put("red", "빨강");
map.put("blue", "파랑");
map.put("yellow", "노랑");
map.put("green", "초록");
map.put("white", "흰색");
System.out.println(map.size());
System.out.println(map);
System.out.println(map.get("yellow"));
// 부분검색(키를 대상으로) == TreeSet메서드와 유사
System.out.println(map.firstKey());
System.out.println(map.lastKey());
System.out.println(map.firstEntry());
System.out.println(map.lastEntry());
System.out.println(map.headMap("m"));
System.out.println(map.tailMap("m"));
System.out.println(map.subMap("m", "x"));
// 1순위
// - ArrayList, HashMap, HashSet
// 2순위
// - LinkedList, Queue, Stack, TreeSet
// 3순위
// - TreeMap, Properties, (Vector), (HashTable)
// 람다, 람다식(Lambda Expression)
// - 함수형 프로그래밍 스타일 지원
// - JDK 1.8 도입
// - 람다식을 사용하면 코드가 간결해지고, 컬렉션을 다루기 쉬워진다.
// - 람다식은 자바의 메서드와 유사
// - 매개변수를 가지는 코드블럭
// - 자바의 람다식을 인터페이스를 통해서 만들어진다.(**** 자바에서만 볼 수 있는 특징)
// 람다식 기본 표현(문법)
// - (자료형 매개변수) -> { 실행코드; }
// a. 매개변수 : 메소드의 매개변수와 동일
// b. -> : 화살표(Arrow). 코드 블럭을 호출하는 역할
// c. 실행코드 : 메서드의 구현부와 동일한 역할
// 이 자체가 문법!!! 람다식!
// (int n) -> { System.out.println(n); }
MyClass m1=new MyClass();
m1.test();
// *** 인터페이스를 구현한 클래스 객체는
// 되도록 인터페이스 변수를 만들어서 저장하는 것이 좋다.
MyInterface m2=new MyClass();
m2.test();
// 익명객체
MyInterface m3=new MyInterface() {
@Override
public void test() {
System.out.println("익명 객체에서 구현한 메서드");
}
};
m3.test();
// 람다식
// - 자바의 람다식은 익명 객체 표현을 대신한다.(익명객체를 보다 편하게 쓰라고 만든)
MyInterface m4=()->{
System.out.println("람다식에서 구현한 메서드"); // 함수형프로그래밍
};
m4.test();
// 람다식코드
// - 인터페이스 변수 = 람다식;
// ex) MyInterface m4=()->{};
// - 자바는 메서드를 독립선언하거나, 저장소에 저장을 하지 못한다.
// - 결국 자바에서 람다식을 다루기 위해서 반드시 인터페이스를 사용해야 한다.
// 람다식에 사용하는 인터페이스
// 1. 반드시 추상 메서드를 1개만 가져야 한다. ( 이름이 없어서 구별을 못함!)
// 2. 람다식을 저장하는 인터페이스를 '람다식의 타겟 타입(Target Type)'이라고 부른다.
// 3. 람다식을 저장하는 인터페이스는 추상 메서드를 단 1개만 가지는데,
// 이런 인터페이스들을 '함수형 인터페이스(Functional Interface)'라고 부른다.
// The target type of this expression must be a functional interface
// 람다식 패턴(=메서드 패턴)
// 1. 매개변수 O, X
// 2. 반환값 O, X
// (1) 매개변수X, 반환값X
NoParameterNoReturn pr1=new NoParameterNoReturn() {
@Override
public void call() {
System.out.println("pr1");
};
};
NoParameterNoReturn pr2=()->{
System.out.println("pr2");
};
pr1.call();
pr2.call();
// (2) 매개변수O, 반환값X
parameterNoReturn pr3=(int num)->{System.out.println(num);};
pr3.call(100);
pr3.call(200);
parameterNoReturn pr4=num->{System.out.println(num);};
pr4.call(300);
pr4.call(400);
parameterNoReturn pr5=num->{System.out.println(num);};
pr4.call(500);
pr4.call(600);
// (3) 매개변수X, 반환값O
NoParameterReturn pr6=()->{return 10;};
System.out.println(pr6.call());
NoParameterReturn pr7=()->{return (int)(Math.random()*10);};
System.out.println(pr7.call());
NoParameterReturn pr8=()->20; // 이렇게 return 키워드와 블럭 생략도 가능
System.out.println(pr8.call());
// (4) 매개변수O, 반환값O
parameterReturn pr9=(int a, int b)->{return a+b;};
System.out.println(pr9.call(10, 20));
parameterReturn pr10=(a, b)->a+b; // 생략의 최종 형태
System.out.println(pr10.call(10, 20));
ArrayList<Integer> nums=new ArrayList<Integer>();
nums.add(100);
nums.add(500);
nums.add(300);
nums.add(400);
nums.add(200);
System.out.println(nums);
코드를 입력하세요
// 익명객체를 사용했던 방법
// nums.sort(new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return o1-o2;
// }
// });
// 익명객체를 사용했던 방법을 람다식을 이용한 방법으로 바꿈(******)
nums.sort((o1, o2)->o1-o2);
System.out.println(nums);
Ex84 : 람다식 이해. 내가 람다식을 직접 만들어서 직접 사용
Ex85 : JDK에서 제공하는 여러 람다식과 관련된 기능을 사용하고 싶으면...
Ex85는 자바에서 미리 만든 JDK를 사용하는 방법!
우리가 람다식을 사용하려면 인터페이스를 만들어야 하는데, JDK 이용하면 람다식만 작성하면 됨
함수형 인터페이스, Functional Interface
JDK 1.8부터 제공되는 인터페이스
람다식 저장용
표준 API 함수형 인터페이스
1. Consumer : 매개변수O, 반환값X
2. Supplier : 매개변수X, 반환값O
3. Function : 매개변수O, 반환값O. 자유도 높음.
4(3-1). Operator : 매개변수O, 반환값O. 매개변수를 연산 후 결과 반환
5(3-2). Predicate : 매개변수O, 반환값O. 매개변수를 논리 판단한 후 반환
// Consumer
// - 매개변수를 받아서 소비하는 일을 구현(소비하니까 반환값 없음)
// - acceptXXX() 추상 메서드
Consumer<String> c1=name->System.out.println(name);
c1.accept("홍길동");
c1.accept("아무개");
Consumer<Integer> c2=n->{
for(int i=0;i<n;i++) {
System.out.println(i);
}
};
c2.accept(10);
BiConsumer<String, Integer> c3=(name, age)->{
System.out.println("이름 : "+name);
System.out.println("나이 : "+age);
};
c3.accept("홍길동", 20);
// Supplier
// - 반환값만 제공하는 메서드
// - getXXX()
Supplier<String> s1=()->{ return "홍길동";};
Supplier<Integer> s2=()->100;
System.out.println(s1.get());
System.out.println(s2.get());
// Function
// - 함수 역할의 메서드 제공
// - applyXXX()
// Function<T, R>
// - T : 매개변수
// - R : 반환값
Function<String, Integer> f1=name->name.length();
System.out.println(f1.apply("홍길동"));
System.out.println(f1.apply("대한민국"));
Function<Integer, String> f2=num->num>0?"양수":"음수";
System.out.println(f2.apply(100));
System.out.println(f2.apply(-50));
// Operator
// - Function의 서브셋
// - 주로 매개변수값을 연산 처리 후 반환하는 역할
// - 매개변수의 타입과 반환값 타입이 동일하다.(연산자 특징)
BiFunction<Integer, Integer, Integer> bf1 = (a, b) -> a + b;
BinaryOperator<Integer> bo1 = (a, b) -> a - b;
System.out.println(bf1.apply(10, 20));
System.out.println(bo1.apply(100, 50));
// Predicate
// - Function의 서브셋
// - 주로 매개변수값을 조사해서 논리값을 반환하는 역할
Function<Integer, Boolean> f1=n->n>0;
Predicate<Integer> p1=n->n>0;
if (f1.apply(10)) {
System.out.println("양수");
}else {
System.out.println("음수");
}
if(p1.test(-10)) {
System.out.println("양수");
}else {
System.out.println("음수");
}