참고링크
•
개발자 로드맵 링크 : roadmap.sh
Map 컬렉션 - Hashtable
•
Hashtable 은 HashMap과 동일한 내부 구조를 가지고 있으며,
동기화된 메소드로 구성되어 있어서 멀티 스레드가 동시에 Hashtable 메소드를 실행할 수 없다는 점에서 차이가 있다.
•
즉, 멀티 스레드 환경에서도 안전하게 객체를 추가, 삭제할 수 있다.
Map 컬렉션 - Properties
•
Properties는 Hashtable의 자식 클래스이기 때문에 Hashtable의 특징을 그대로 가지고 있다.
•
Properties는 키와 값을 String 타입으로 제한한 컬렉션으로, 확장자가 .properties인 프로퍼티 파일을 읽을 때 사용한다.
Properties properties = new Properties();
properties.load(xxx.class.getResourceAsStream("파일명.properties"));
Java
복사
TreeMap
•
이진 트리 기반으로 검색 기능을 강화한 Map 컬렉션이다.
•
TreeSet과의 차이점은 키와 값이 저장된 Entry를 저장한다.
•
TreeMap에 저장되는 객체는 저장과 동시에 오름차순으로 정렬된다. (키를 기준으로 낮은 것은 왼쪽 자식 노드에, 높은 것은 오른쪽 자식 노드에 저장)
•
Comparable 인터페이스를 구현하고 있는 객체만이 정렬 가능하다.
TreeMap<K, V> treeMap = new TreeMap<K, V>();
TreeMap<K, V> treeMap = new TreeMap<>();
Java
복사
컬렉션 자료구조 - Comparable과 Comparator
•
TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 저장과 동시에 오름차순으로 정렬된다.
•
어떤 객체든 정렬될 수 있는 것은 아니고 객체가 Comparable 인터페이스를 구현하고 있어야 가능하다.
•
Integer, Double, String 타입은 모두 Comparable을 구현하고 있기 때문에 상관 없지만,
사용자가 직접 정의한 객체를 저장할 때에는 반드시 Comparable을 구현하고 있어야 한다.
•
Comparable 인터페이스에는 compareTo() 메소드가 정의되어 있다. 따라서 사용자 정의 클래스에서 이 메소드를 재정의해서 비교 결과를 정수값으로 반환해야 한다.
•
Comparator는 함수형 인터페이스다.
(추상 메소드 한 개있는 것을 함수형 인터페이스라고 함)
package com.collection.map;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class Book implements Comparable<Book> {
private String title, isbn;
private int year;
@Override
public int compareTo(Book o) {
// return this.title.compareTo(o.getTitle());
// 제목 글자수 오름차순 정렬
Integer thisTitleLength = this.title.length();
Integer otherTitleLength = o.title.length();
return thisTitleLength.compareTo(otherTitleLength);
}
}
//===========================================================================
package com.collection.map;
import java.util.TreeSet;
public class SortExample {
public static void main(String[] args) {
TreeSet<Book> bookSet = new TreeSet<>();
bookSet.add(new Book("개를 훔치는 완벽한 방법", "B1", 2002));
bookSet.add(new Book("수상한 장미마을", "B2", 2000));
bookSet.add(new Book("위대한 개츠비", "B3", 1980));
bookSet.add(new Book("언어의 온도", "B4", 2015));
bookSet.add(new Book("아몬드", "B5", 2006));
System.out.println(bookSet);
}
}
Java
복사
컬렉션 자료구조 - LIFO와 FIFO 컬렉션
•
후입선출(LIFO: Last In First Out)은 나중에 넣은 객체가 먼저 빠져나간다.
•
선입선출(FIFO: First In First Out)은 먼저 넣은 객체가 먼저 빠져나가는 구조를 말한다.
•
컬렉션 프레임워크는 LIFO 자료구조를 제공하는 스택(Stack)클래스와 FIFO 자료구조를 제공하는 큐(Queue) 인터페이스를 제공한다.
Stack<E> stack = new Stack<E>();
Stack<E> stack = new Stack<>();
Java
복사
•
Queue 인터페이스는 FIFO 자료구조에서 사용되는 메소드를 정의한다.
•
Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList이다. 따라서 LinkedList 객체는 Queue 인터페이스 변수에 아래와 같이 대입할 수 있다.
Queue<E> queue = new LinkedList<E>();
Queue<E> queue = new LinkedList<>();
Java
복사
동기화된 컬렉션
•
여러 스레드가 동시에 컬렉션에 접근하면 의도하지 않게 요소가 변경될 수 있다.
•
Vector와 HashTable은 동기화된(Synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드 환경에서 안전하게 요소를 처리할 수 있지만, 다른 자료구조들은 동기화된 메소드로 구성되어 있지 않아 멀티 스레드 환경에서 안전하지 않다.
•
만약 멀티 스레드 환경에서 사용하고자 한다면, 비동기화된 메소드를 동기화된 메소드로 래핑하는 Collections의 synchronizedxxx() 메소드를 사용하면 된다.
수정할 수 없는 컬렉션
•
요소를 추가, 삭제할 수 없는 컬렉션은 수정할 수 없는 컬렉션이라 한다.
•
컬렉션 생성시 저장된 요소를 변경하고 싶지 않을 때 사용할 수 있다.
•
수정할 수 없는 컬렉션 만드는 방법
◦
List, Set, Map 인터페이스의 정적 메소드인 of() 로 생성
List<E> immutableList = List.of(E element1, …);
Set<E> immutableSet = Set.of(E element2, …);
Map<E> immutableMap = Map.of(K k1, V v1, …);
Java
복사
◦
List, Set, Map 인터페이스의 정적 메소드인 copyOf( )로 생성
List<E> immutableList = List.copyOf(Collection<E> coll);
Set<E> immutableSet = Set.copyOf(Collection<E> coll);
Map<E> immutableMap = Map.copyOf(Map<K, V> map);
Java
복사
◦
배열로부터 수정할 수 없는 List 컬렉션 생성
String arr = { … };
List<String> immutableList = Arrays.asList(arr);
Java
복사
람다식
•
메서드를 “하나의 식” 으로 표현한 것이다.
•
메서드의 이름과 반환값이 없어지므로 “익명함수” 라고도 한다.
•
함수형 프로그래밍:
◦
함수를 정의하고, 해당 함수를 데이터 처리부로 보내 데이터를 처리하는 기법. 데이터 처리부에서 데이터만 가지고 있을 뿐, 데이터 처리 방법이 정해져 있기에 외부에서 제공된 함수에 의존한다.
⇒ 추상 메소드를 정의하고, 추상 메소드를 오버라이딩된 곳으로 보내서 처리하도록 시킨다.
추상 메소드 쪽에서는 데이터만 가지고 있으며 처리 방법은 정해져 있지 않다.
•
람다식은 데이터 처리부에 제공되는 함수 역할을 하는 매개변수를 가진 중괄호 블록으로, 익명 구현 객체로 변환하여 동작한다.
•
익명 구현 객체를 람다식으로 표현하기 위해서는 인터페이스가 단 하나의 추상 메소드만을 가지고 있어야 한다.
•
단 하나의 추상 메소드를 가지고 있는 인터페이스를 함수형 인터페이스라고 부른다.
@FunctionalInterface 어노테이션을 붙인다.
•
람다식에서 매개변수가 하나인 경우에는 소괄호 생략이 가능하고, 실행문이 한 줄인 경우 중괄호 생략이 가능하다.
package com.review;
public class CarExample {
public static void main(String[] args) {
Driver inkyu = new Driver();
inkyu.drive(new K5());
inkyu.drive(new Tesla());
inkyu.drive(new Car() {
@Override
public void run() {
System.out.println("모르는 차인데도 운전이 된다.");
}
});
inkyu.drive(() -> System.out.println("이름 없는 슈퍼카 부릉부릉"));
}
}
Java
복사
package com.lambda;
public class LambdaExample {
public static void main(String[] args) {
MyInterface mi = new MyInterface() {
@Override
public void action(int x) {
System.out.println("숫자 " + x + "을 활용한 동작");
}
};
mi.action(3); // 같은 동작
MyInterface li = (x) -> System.out.println("숫자 " + x + "을 활용한 동작");
li.action(3); // 같은 동작
}
}
Java
복사
인터페이스, 람다식에 대한 이해를 위해
•
역할, 구현
◦
자동차 역할: 움직이는 역할
◦
운전자 역할: 자동차를 움직인다.
람다식 실행
•
람다식 실행 방법
•
함수형 인터페이스의 추상 메소드에 리턴값이 있을 경우, 람다식은 아래와 같이 작성 가능하다.
•
return문 하나만 존재하는 경우에는 중괄호와 함께 return 키워드를 생략할 수 있다.
람다식 - 메소드 참조
•
메소드 참조(Method Reference)는 자바 8에서 도입된 기능으로, 기존 메소드나 생성자를 참조하여 람다 표현식을 단축할 수 있다. 이를 통해 코드의 가독성을 향상시키고, 불필요한 매개변수를 제거할 수 있다.
•
람다식은 매개변수를 받아 값을 전달하는 역할을 할 수 있지만,
메소드 참조를 이용하면 불필요한 매개변수를 제외하고 더 간결하게 작성할 수 있다.
•
예제
package com.lambda5;
@FunctionalInterface
public interface Calculable {
double calc(double x, double y);
}
Java
복사
package com.lambda5;
public class Person {
public void action(Calculable c) {
double result = c.calc(10, 4);
System.out.println("결과 : " + result);
}
}
Java
복사
package com.lambda5;
// 서비스 로직만 따로 구현
public class CalculateService {
public static double sum(double x, double y) {
return x + y;
}
public static double multiply(double x, double y) {
return x * y;
}
}
Java
복사
package com.lambda5;
public class MethodReferenceExample {
public static void main(String[] args) {
Person p = new Person();
// p.action(인터페이스); -> 인터페이스의 메소드 calc(10, 4) 호출 -> 그 결과 출력
// 추상 메소드 [double calc(double x, double y)]
p.action((x, y) -> CalculateService.sum(x, y));
p.action(CalculateService::sum); // 위 코드와 동작 같음
p.action((x, y) -> CalculateService.multiply(x, y));
p.action(CalculateService::multiply); // 위 코드와 동작 같음
}
}
Java
복사