5. 자바 컬렉션과 제네릭
1. 학습 개요
컬렉션 Object 제네릭 이터레이터foreach 스트림API
컬렉션이란
배열을 가지고 직접 사용하는 것들을 서비스개념으로 사용할 수 있게 해주는 것
데이터 수집 데이터 삭제 등 안에 저장소에 대한 내용을 숨기고 안에 내용을 알필요가 없다.
add로 쉽게 담는다. 추가할위치를 알아서 잡는다.
컬렉션은 왜 사용하는가?
1.데이터관리를 직접할 필요가없다.
2.배열일경우 필요에 따라 늘릴 수 없는데 컬렉션은 알아서 늘어남
결론적으로 가변길이 배열이라고 할 수도 있다.
2. 정수형 컬렉션 구현하기
컬렉션의 기본기능은 .add(int e) / .remove(int e) / .clear() / .szie()가 있다.
public class IntList {
private int[] nums;
private int current;
public IntList() {
nums = new int[3];
current = 0;
}
public void add(int num) {
nums[current] = num;
current++;
}
public void clear() {
current = 0;
}
public int size() {
return current;
}
public int get(int index) {
if (current < index) {
throw new IndexOutOfBoundsException();
}
return nums[index];
}
}public class Program {
public static void main(String[] args) {
IntList list = new IntList();
list.add(3);
list.add(5);
list.clear();
int size = list.size();
System.out.println("size: " + size);
list.add(7);
int num = list.get(0);
System.out.println("num: " + num);
}
}직접 구현해보았다.
3. Object 클래스의 필요성
정수형으로 만들었는데 정수만 담고싶다.
Exam으로 담고 싶다? Exam컬렉션필요함.
사용자마다 다르니 사용자마다 만들어야함.
이런 자료형들을 다담을 수있는 컬렉현 하나를 담으면 매우 편할 것같다.
모든 클래스는 Object이다 Obeject를 상속받고 있다.
따라서 모든 객체는 Object형식으로 배열을 만들면 모든 객체들이 참조할 수 있다.
Object는 공통 자료형으로 존재할 수 있다.
4. Wrapper 클래스와 Auto Boxing/UnBoxing
Obeject는 모든 객체를 참조할 수있는 참조형식인데 값을 참조할 수없다.
Obejct obj = 3; -> 불가능
-> Boxing
Object obj = new Integer(3);
공간을 가지도록 박스에 담아야한다. 객체로 만들어서 담는 것이다.
이박스에 담는 작업을 박싱이라고 한다. 옛날에는 박싱을 해야 담긴다.
jdk1.5부터 오토박싱이 되기 시작했다. 참조가 저절로 이루어져서 가능은 하다.
Obejct obj = 3;
->UnBoxing
int x = obj.intValue();로 꺼내야하는데 이것도 자동으로 처리해준다.
그래서 값을 담으려면 int x = 3 ; Integer x = 3; 값형식으로 담거나 박싱이 이루어지고 참조하는 방식으로 할 수 있게 되었다.
똑같다고 생각하면 안되고 후자를 쓰면 내부적으로 박싱 언박싱이 계속 이루어져서 메모리를 먹으니 필요하지 않으면 사용하지 말자.
자동박싱언박싱때문에 값처럼 사용되서 헷갈릴수잇다.
모든데이터를 일괄적으로 관리하자면? Object배열로 담으면된다.
5. Object 콜렉션으로 변경하기
다양한 형식으로 만들 수있다는 장점이 있다.
int를 Object로 바꿔주면 된다.
그런데 이것을 꺼내서 사용할때 무엇으로 꺼낼지 모르겠다.
또한 저장된게 여러가지라서 하나를 정하기가 어렵다.
그래서 변환할때 마다 무슨 형이니를 물어봐야한다.
int num = (Integer) list.get(0); 형변환을 해줘야한다.
범용자료형이다보니 어떤값을 담고있는지 확신이 안되고 확신한다해도 형변환을 해줘야한다는 단점이 있다.
6. Generic 이란
Obeject형태이지만 반대로 불편한점이 있엇다.
그래서 형식을 비우는 코드를 주고 처리되도록 하는 방식이 생겻다.
그런데 이것은 c++에서의 탬플릿 이다.
자바에서는 object로 만들고 뺄때 사용자가 원하는 것으로 형변환해준다.
무엇이든 될수잇는 제네릭이다.
GList<Integer> list = new GList<>();
형식을 결정해서 실행한다.
public class GList<T> {
<타입, 두번째 타입>
객체생성은 Object로 하되 들어오는 값을 T형으로 하고
나가는값을 T로 해준다.
public class Program {
public static void main(String[] args) {
GList<Integer> list = new GList<>();
list.add(3);
list.add(5);
list.clear();
int size = list.size();
System.out.println("size: " + size);
list.add(7);
int num = list.get(0); //Object -> Integer
System.out.println("num: " + num);
}
}public class GList<T> {
//<타입, 두번째 타입>
private Object[] nums;
private int current;
public GList() {
nums = new Object[3];
current = 0;
}
public void add(T num) {
nums[current] = num;
current++;
}
public void clear() {
current = 0;
}
public int size() {
return current;
}
public T get(int index) {
if (current < index) {
throw new IndexOutOfBoundsException();
}
return (T) nums[index];
}
}정수형으로 선언햇으니 정수만 담고 뽑을 수 있다.
7. 가변크기 컬렉션으로 변경하기 #1
배열의 문제점은 크기가 정해져잇어서 늘릴수가 없다.
mim을 정해두고 늘어나면 새로운 배열을 만들어서 복사후 크기를 점점 늘리는것이다.
mim을 capacity라고 잡고 늘릴양을 amount라고 할것이다.
!!혼자해보기!!
add메소드에 넣으면된다. 넣을때 모자란지를 조건검사한다.
1.amount개 확장한 새로운 배열 temp를 생성
2.list에 있는 데이터를 temp배열로 옮기기
3.temp가 참조하는 객체를 list가 참조하게 한다.
4.capacity 값을 amount개 증가시킨다.
public void add(T num) {
if(capacity <= current) {
Object[] temp = new Object[capacity + amount];
for (int i = 0; i < temp.length; i++) {
temp[i] = nums[i];
}
data = temp;
capacity += amount;
}
nums[current] = num;
current++;
}8. 가변크기 컬렉션으로 변경하기 #2
!!풀이!!
public void add(T num) {
if(capacity <= current) {
Object[] temp = new Object[capacity + amount];
for (int i = 0; i < current; i++) {
temp[i] = nums[i];
}
nums = temp;
capacity += amount;
}
nums[current] = num;
current++;
}9. 자바 언어에 포함된 콜렉션 프레임워크
컬렉션을 직접 구현해봤는데 직접구현할 필요가 없다.
자바언어가 제공하고 있다. 어떻게 구현됫는지를 보고자 직접만들엇다.
인터페이스로서 기능을 가지고 있다.
사진참조
실제구현체로 List는 ArrayList / LinkedList / Stack이잇다.
ArrayList 이것을 기본적으로 사용하고자 한다.
Map은 HashedMap사용하려고한다.
그런데 필요에 따라 저장하는데 왜 여러개 이나?
선형으로 저장한다면? 하나씩 꺼내야되서 안좋을때도 있다.
이걸 빠르게 검색한다면?
비선형데이터구조 Tree모양으로 저장한다면 찾아보기 쉽다
링크(참조 포인터 등)으로 연결된 데이터
선형은 중간에 삭제하면 하나식 밀어야함.
링크로 하면 참조 포인터로 다음놈이 어떤놈인지 찾는거임.
그래서 다양한 형태가 있다. 내부적으로 데이터를 다루는 방법이 다르다.
다루는것은 데이터 스트력처를 따로 공부해라.
set hashset list ArrayList map HashMap 3가지만 일단 공부하자.
10. Set/List/Map 콜렉션
set-hashset
list-ArrayList
map-HashMap
이전에 직접 구현한 GList가 List와 같은 기능을 한다.
List<Integer> list = new ArrayList<>();
Set은 다음처럼 만든다.
Set<Integer> set = new HashSet<>();
무슨차이가 잇나? 식별자의 차이점이 있다.
list는 인덱스로 식별이 가능하다.
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(5);
list.add(5);
list.add(5);
list.add(5);
System.out.println(list.get(0)); //3
System.out.println(list.size()); //5set은 식별자가 없어서 값이 곧 식별자이다.
식별자는 중복이 될 수 없기 때문에 중복값은 저장이 안된다.
set에서는 특정값을 꺼낼 일이 없다.
그래서 중복제거용으로 사용한다.
Set<Integer> set = new HashSet<>();
set.add(3);
set.add(6);
set.add(7);
set.add(7);
set.add(7);
System.out.println(set.size()); //3Map은 키와 값으로 값을 저장한다.
Map<String, Integer> map = new HashMap<>();
map.put("id", 3);
map.get("id");일반적인 배열처럼 관리하고싶다면 list
수집할대 중복제거하려면 set
속성을 가진 개체를 클래스로 정의해서 사용해야하는데 클래스로 정의하지않고 식별하는게 필요할때 map을 사용한다.
자바 스레드와 비동기처리
1. 학습안내
스레드개념 스레드관리 동기화 동기화도구 스레드풀 스레드에 안전한 컬렉션 포크/조인
2.멀티 태스킹과 프로세스 Context스위칭
스레드가 나오기전의 상태 스레드 이전에 비동기처리 스레드 왜나왓는지
실행해주는 프로그램은 hdd에 잇는다. 메모리는 휘발성이라 os가 hdd에 잇는것을 끌어올려와서(load) 실행한다.
실제로 메모리에서 돌리는 프로그램이 프로세스이다.
이 프로세스들이 동시에 동작하고 잇나? 그렇진 않다.
cpu가 하나면 하나만 실행한다.
멀티태스크 환경이라고 한다. cpu가 동시에 실행되는 것처럼 착각시키는 것이다.
빠르게 순회하면서 조금씩 처리한다.
os가 시분할 을 통한 동시 실행을 지원하는 것처럼 보이게 하는 것이다.
어떤일이 일어나면 작업중에 잠깐 멈춰야한다. 멈추는 시점을 기억해야한다. 잠깐 저장할수잇는 게필요하다.
그래서 프로세스마다 문맥 Context가 필요하다. 문맥객체를 저장하고 이게 스위칭 되면서 실행되는 것이다.
이 프로세스간의 스위칭이 크게 늘어나면? 문제가 생긴다.
3. 자식프로세스를 많이 가지는 욕심꾸러기 프로세스
모든 것을 동기화로 실행한다면 중간에 오래걸리면 다음으로 가지 못하게된다.
백그라운드에서 비동기형 프로세스들이 필요하다.
옛날에는 검색프로그램과 다운로드 프로그램을 따로만들엇다.
그래서 fork()라는 함수로 다른 프로그램을 로드햇다.
프로세스에 올라가는순간 os가 시간을 분할해준다.자식 프로세스들로 비동기를 구현햇엇다.
프로세스가 많아지면 컨텍스트 스위칭하는데 어려움이 잇엇다.
전체적으로 성능저하가 일어낫다. 스위칭하는 시간도 필요하다.
점점 이과정이 많아지면 다른 프로세스들이 일을 처리할 시간이 모자라게 된다.
1.형평성을 맞추자
2.스위칭시간을 줄여보자
3.자식의 정보를 위의 프로세스에 전달하고싶다. 자식부모간의 데이터공유
현실적인 시분할을 하고 싶게 되엇다. 이것을 대신할 수잇는 것이 스레드이다.
4. 프로세스에서 스레드 문맥 스위칭으로
시간을 단위로 분할햇는데 더 작은단위로 나누고싶다.
더작은단위인 스레드로 나눌 수 있게 되엇다.
시간은 프로세스에게 제공하고 비동기가 필요하다면
하부 단위의 시간을 분해할 수잇게 스레드를 제공하게된다.
스레드를 함으로써 프로세스간 형평성이 처리되엇다.
안에서 흐름을 나누는 것이라 전역변수를 저장하는 스택영역과 처리부분만 스위칭하면된다.
스위칭하는 과정이 두개만 하면되서 효율적으로 되엇다.
스레드는 문맥을 따로둠으로서 시간을 나눠서실행될수잇게 되엇다.
5. 멀티 스레드를 위한 예제 준비하기
동기형예제 숫자 100개출력
public class Ex1Program {
public static void main(String[] args) {
print1();
print2();
for (int i = 0; i < 100; i++) {
System.out.printf("main : %d\n", i + 1);
}
}
private static void print1() {
for (int i = 0; i < 100; i++) {
System.out.printf("sub1 : %d\n", i + 1);
}
}
private static void print2() {
for (int i = 0; i < 100; i++) {
System.out.printf("sub2 : %d\n", i + 1);
}
}
}2023.02.16 후기
제네릭과 컬렉션을 배웟지만 수동으로 컬렉션을 만드는 것은 생각하지 못햇다.
컬렉션을 사용할때 제네릭을 왜 넣는지를 알게 되는 계기가되엇다.
스레드를 개념적으로 어떻게 사용하는지와 어떤 역할을 하는지는 알고있었는데 어떻게 생기게 되었는지를 알게되니 왜 사용하는지 알 것같다.
'기초단계 > JAVA' 카테고리의 다른 글
| 2023.02.17-2 Java 복습 (0) | 2023.02.17 |
|---|---|
| 2023.02.17-1 Java 복습 (1) | 2023.02.17 |
| 2023.02.16-1 Java 복습 (0) | 2023.02.16 |
| 2023.02.15-2 Java 복습 (0) | 2023.02.15 |
| 2023.02.15-1 Java 복습 (0) | 2023.02.15 |