반응형

**파이썬의 자료형

1.Data 의 분류 방법

1)수정 가능 여부

=>변경 가능(mutable) - 변수

=>변경 불가능(immutable) - 상수

=>Literal: 사용자가 직접 입력한 데이터

정수: 10

실수: 10.3

bool: True, False

복소수: 정수 +(-) 정수j

 

문자열: '문자열', "문자열", '''문자열''', """문자열"""

list: [데이터 나열]

tuple:(데이터 나열)

set: {데이터 나열}

dict:{key:data, key:data...}

 

데이터 없음:None

 

=>변수의 생성 및 수정 과 삭제

이름 = Literal, 연산식, 함수 등

영역 내에서 이름이 처음 등장하면 생성

영역 내에서 이름이 처음이 아니면 수정

영역은 동일한 들여쓰기이면 같은 영역

 

변수는 영역이 종료되면 소멸됩니다.

del(변수)를 이용해서 강제로 종료하는 것도 가능

 

2)데이터가 가리키고 있는 개수에 따른 분류

=>scala data: 1개의 데이터 - 분석의 대상이 아닙니다.

=>vector data: 0개 이상의 데이터 - 분석의 대상

=>scala data는 정수, 실수, 복소수, bool, 문자열(scala data가 되기도 하고 vector data),날짜

=>vector data는 문자열, list(array 라고도 합니다.), tuple, set, dict

 

3)형태에 따른 분류

=>정형 데이터: 테이블로 바로 변환이 가능한 데이터 - 관계형 데이터베이스에 존재 - 기술통계

=>비정형 데이터: 테이블로 바로 변환이 되지 않는 문자열이나 이미지 및 음성 데이터 같은 것들로

머신런닝을 적용할 때는 숫자로 변환해서 사용(이러한 작업을 인코딩 이라고 합니다.) - 거리

=>반정형 데이터: 초기 상태는 비정형 데이터처럼 보이지만 가공을 하면 정형 데이터로 변환할 수 있는 데이터로 json 이나 xml 데이터 등 - web 이나 기기로부터 직접 가져온 데이터

 

2.bool

=>True False 1개만 저장하는 자료형

=>0이 아닌 숫자나 None 이 아닌 집단 자료형의 데이터들도 True로 간주하고 0이나 None인 집단 자료형의 데이터는 False로 간주

=>bool을 숫자와 산술연산을 하면 True 1로 간주하고 False 0으로 간주해서 연산

=>강제로 bool로 만들고자 하는 경우에는 bool(데이터)

 

 

#bool 덧셈
b = True
result = b + 2 #b 1로 간주해서 1+2 = 3
print(result)

 

 

3.int

=>정수 자료형

=>다른 자료형을 정수로 변환하고자 할 때는 int(데이터)

정수로 된 문자열이면 정수로 변환되고 실수로 만들어진 문자열이면 에러가 발생

실수를 대입하면 소수 버림

 

f = '10.7'

x = float(f)

n = int(x) # n 10

 

4.float

=>실수 자료형

=>실수는 표현 못하는 숫자가 있습니다.

부정확합니다.

=>실수로 변경하고자 할 때는 float(데이터)

=>데이터를 읽었을 때 문자열로 읽어진 경우 숫자로 변환해야 하는 경우가 많기 때문에 변환방법을 숙지

 

5.sequential type(데이터를 순서대로 저장하는 자료형)

=>str, bytes, list, tuple

1)인덱싱

데이터[인덱싱]: 인덱싱 번째 데이터가 리턴, 음수를 사용하면 뒤에서부터

 

2)슬라이싱

=>데이터[시작위치:종료다음위치:간격] : 시작위치부터 종료다음위치 앞까지 간격단위로 리턴

=>종료위치를 생략하면

=>끝까지 간격을 생략하면 1

 

3)연결하기: 동일한 자료형끼리 +를 하면 연결

 

4)반복하기: 정수와 *

 

5)데이터 개수: len(데이터)

 

6)존재 여부 확인: in 연산자

 

6.str(문자열)

=>한 줄 문자열은 작은 따옴표 나 큰 따옴표로 묶으면 됨

=>여러 줄 문자열은 작은 따옴표나 큰 따옴표 3번으로 묶으면 됨

=>문자열은 수정할 수 없습니다.

문자열은 인덱싱이나 슬라이싱으로 데이터를 읽는 것만 가능하지 대입하는 것은 안됩니다.

 

1)제어문자 : \다음에 하나의 문자를 입력해서 특수한 기능 부여

\n : 줄바꿈

\t :

\', \"

\\: \

      파이썬에서는 윈도우더라도 디렉토리 기호는 / 사용이 가능

 

2)format 메소드

=>데이터에 서식을 지정해서 문자열을 생성하는 메소드

=>서식은 "{데이터의 인덱스:서식}".format(데이터) 로 지정

=>데이터의 개수는 제한이 없습니다.

 

7.bytes

=>바이트 배열

=>네트워크 나 파일의 내용을 읽거나 전송할 때 사용

원래 네트워크나 파일의 전송단위는 byte

이 기종 간에 데이터를 주고받을 때는 byte 단위로 데이터를 전송한 후 복원합니다.

=>문자열을 bytes 로 만들 때는 b'문자열'

=>bytes를 문자열로 만들 때는 decode(byte 배열)

 

8.list

=>데이터를 순서대로 저장한 자료구조

=>내부 데이터를 읽고 쓰는 것이 가능

1)생성

=>[데이터 나열]

=>list(__iter__가 구현된 객체): list로 변환

 

2)list 에 연산을 수행해서 새로운 list 만들기

[연산식 for 임시변수 in list] : list의 데이터를 임시변수에 대입한 후 연산을 수행해서 새로운 list 생성

 

3)조건식을 적용해서 새로운 list 만들기

[연산식 for 임시변수 in list if 조건]

 

4)함수에 대입할 때는 [ ]를 붙이지 않습니다.

 

#list에 연산을 해서 새로운 list 만들기

li = [10, 4, 9, 23, 26]

#데이터를 순차적으로 접근

for imsi in li:

    print(imsi, end='\t')

print()

#li의 요소들을 k에 하나씩 대입해서 3을 곱해서 새로운 list 생성

print([k*3 for k in li])

#필터링 - 짝수만 골라내기 - 텍스트 마이닝에서 많이 사용하는 문법

print([k for k in li if k % 2 == 0])

#함수에 사용할 때는 []를 생략

print(sum(k for k in li if k % 2 == 0))

 

li = ['겨울', '', '']

print([k for k in li if len(k) > 1])

 

 

li = [10,20,30,40,50]

t = li[0:3:1] #슬라이싱 - 복제가 됩니다.

#슬라이싱 데이터와 원본 데이터는 다른 데이터

print(t)

t[0] = 1000 #복제된 데이터를 수정해도 원본 데이터에는 아무런 영향이 없음

print(li)

 

5)append, insert, delete, reverse, sort, count - 매개변수로 대입된 데이터의 개수를 구해주는 메소드

등을 소유

 

6)list 안에 list 생성 가능

=>2차원 list - 이미지나 문자열 데이터를 읽어서 변형하면 이 구조

 

[[데이터], [데이터]....]

 

=>이미지는 바로 numpy ndarray로 바로 변환해서 사용하기 때문에 2차원  list로 만드는 경우는 드물지만 알아는 두어야 합니다.

머신러닝은 순수한 데이터만 가지고 작업을 수행합니다.

 

국어 영어

10   20

30   70

 

=> 저 데이터를 아래처럼 변경해야만 머신러닝에서 사용 가능

10   20

30   70

 

안녕하세요 반갑습니다.

어서오세요 환영합니다.

=>위와 같은 문장을 단어 별로 분해를 해주세요..

 

[[안녕하세요, 반갑습니다.], [어서오세요, 환영하세요]]

 

#2차원 list 인 경우 접근

li = [[100, 300], [400, 200]]

 

#행단위 접근

for imsi in li:

    for temp in imsi:

        print(temp, end='\t')

    print()

print()

 

#열단위 접근 - numpy pandas에는 T 라는 속성을 이용해서 행과 열을 switch

for i in range(0, len(li), 1):

    for j in range(0, len(li[i]), 1):

        print(li[j][i])

 

7.tuple

=>내부 데이터를 수정할 수 없도록 하고 순서대로 배치하는 데이터의 모임

1)생성

(데이터 나열)

1개일 때는 (데이터,)

 

2)각가의 데이터는 인덱싱을 이용해서 접근

 

3)tuple의 데이터는 분할해서 변수에 저장 가능

변수1, 변수2... = 튜플

=>튜플의 값들을 순서대로 변수1, 변수2 에 대입

 

4)함수가 여러 개의 데이터를 리턴해야 할 때 각각의 데이터가 서로 다른 의미를 갖고 모여서 하나를 이루어야 하는 경우 파이썬은 class tuple을 이용

tuple의 데이터를 각각의 의미를 갖는 변수에 대입해서 사용하는 경우가 많습니다.

 

#회귀분석을 하게되면 결과로 기울기와 절편의 값을 리턴합니다.

result = (4, 7) #이 상태면 result[0] 이 기울기, result[1]이 절편

 

slope, intercept = result #0번 데이터가 slope 1번 데이터가 intercept에 대입

print('기울기:', slope)

print('절편:', intercept)

8.dict

=>key value를 같이 저장

1)생성

{key:data, key:data....}

=>data scala 데이터면 하나의 행(Serise)을 만드는 것입니다.

=>data list 이면 테이블(DataFrame)을 만드는 것입니다.

 

2)데이터 접근

dict[key] 를 이용해서 하나 하나의 데이터에 접근

없는 key를 사용하면 에러가 납니다.

파이썬의 매개변수를 만들 때 **args 이런 형태로 만들면 내부적으로 dict 가 됩니다.

우리가 대입할 때는 이름=, 이름=...

실수로 필수 입력 내용을 주지 않으면 에러가 발생합니다.

 

#Key Error : 없는 key를 사용

dictionary = {'name':'park', 'num':1}

print(dictionary['num'])

print(dictionary['age'])

 

3)2개의 list를 가지고 생성

zip(key list, data list)

 

 

 

반응형

'Study > Python' 카테고리의 다른 글

python-13  (0) 2020.10.26
python-12  (0) 2020.10.26
python-11  (0) 2020.10.26
python-10  (0) 2020.10.26
Python-9  (0) 2020.09.12
반응형

**인터페이스 사용

1.    인터페이스

=>final 상수와 추상 메소드 만을 가진 개체

=>최근에는 default method(구현된 메소드)를 소유 가능

=>다른 클래스에 implements 해서 사용, 다른 Property클래스인터페이스에 entends 가능

 

2.    사용 목적

=>다형성 구현을 위해서

=>템플릿 메소드 패턴을 구현하기 위해서

인터페이스에 메소드의 모형을 만들고 클래스에서 구현하는 방식

클래스가 인터페이스를 implements했다면 클래스에는 인터페이스의 메소드가 구현되어 있다는 보장을 할 수 있습니다.

추상메소드는 상속받은 곳에서 반드시 재정의 해야 합니다.

overring안하면 안된다.

최소한 메소드는 만들어져 있다 고 보장할 수 있다.

인터페이스를 다른 말로 부를 때 protocol(규칙,규약,약속)이라고도 합니다.

collection 인터페이스

 

**자료구조(Data Structure)

=>0개 이상의 데이터를 저장하는 방법

=>예전에는 각 자료구조의 특징을 숙지하고 직저 구현을 해서 사용했는데 최근에는 프로그래밍언어에서 자료 구조를 미리 구현해놓고 이 자료구조를 가져다 사용하는 경우가 많습니다.

제공되는 자료구조는 프로그래밍언어마다 다르고 부르는 이름도 다릅니다.

r은 다르다.

자료구조 특징만 알면 된다.

python에서는 list특징만 주고 사용법만 아시면 된다.

=>알고리즘을 잘 설계하더라도 자료구조를 선택하면 속도 향상은 한계가 있습니다.

자료구조 알고리즘 자료구조를 먼저 선택하고 알고리즘을 한다.

=>자바의 경우는 자료구조 관련 클래스들이 java.util패키지에서 제공합니다.

java.lang ->java.util

 

**java.util의 자료구조 관련 인테페이스와 클래스

1.Arrays 클래스

=>배열 관련된 작업을 위한 클래스

=>배열의 특징(Array)

배열은 한 번 생성되면 크기 변경이 안됩니다.

배열은 데이터를 연속적으로 빈 공간 없이 배치해야 합니다.

배열은 공간낭비가 없습니다.

 

연속적으로 배치할 수 있는 빈 공간이 없으면 생성이 불가능

데이터를 삽입하거나 삭제하고자 할 때는 복사해서 작업을 수행해야 합니다.

크기 변경이 안되기 때문에 삽입할려면 새로운 공간을 할당받아서 삽입해야 하고 연속적으로 배치되어야ㅑ 하기 때문에 삭제를 할려면 삭제된 이후의 데이터를 앞으로 당겨야 하는 문제가 발생하기 때문입니다.

c언어는 배열을 stack에서 한다.

stack은 기본적으로  1mb크기다.

int ar[1000000] =>stackOverflow

그래서 c언어는 point만들고 참조형으로 한다.

java는 참조형으로 되여있다.heap에 저장한다.

머신런닝은 c 해야 할 가능성이 있다. python의 모든 라이버러리가 cjava 등으로 되여있다. 많은 양의 데이터 가지고 할때 내부적으로는 c로 하고 가져고 온다. 대부분의 알고리즘은 c로 한다.c가 빠르기 때문이다.

 

삽입은 크기를 추가한다는 옮겨야 하기 때문에 복사하고 해야 한다.

삭제를 할 경우 연속적으로 빈 공간 없이 배치해야 하는 것은 삭제하면 빈공간이 생겨서 앞으로 땡겨야 한다. 그래서 앞으로 땡기는데 시간이 걸린다.

삽입 삭제를 거의 안하면 arrays로 만드는 것이다.

수정은 개수의 변화가 아니라 값이 변하는 것이다.

ar[0] = 10;

ar[0] = 20;//으로 변경

 

2.collection 인터페이스

=>데이터의 모임과 인터페이스

=>ListSet인터페이스에게 상속

=>Collection들에 공통으로 구현해야 할 메소드를 선언

stack    -> push

-> pop

ArrayList : add

list 개열은 add로 하면 좋지 않는가 ?

각기 다를 경우 그래서 인터페이스를 만들고 : add라고 하고 implements stack, ArrayList로 해주면 된다.

이름을 통일하게 하기 위해서 정해줄려고 collection인터페이스를 만들었다.

다시 collection을 분할 시켰다. list, set

 

BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>, Deque<E>, List<E>, NavigableSet<E>, Queue<E>, Set<E>, SortedSet<E>, TransferQueue<E>

 

public interface Collection<E>

extends Iterable<E>

Iterable=> for써서 하나씩 접근 하는 것이다.

python __iterable__

 

3.List 인터페이스

=>데이터를 물리적 또는 논리적인 순서대로 연속해서 저장하는 자료구조 인터페이스

=>ArrayList, LinkedList, Stack, Queue, Deque등에서 구현하거나 상속

python은 기본적으로 LinkedList  이고 문제 생겨서 후에 queue.를 추가하였다.

 

4.Set 인터페이스

=>데이터를 중복없이 해싱을 이용해서 저장하는 자료구조 인터페이스

=>HashSet, LinkedHashSet , TreeSet 클래스에서 구현

 

5.Map 인터페이스

=>keyValue를 쌍으로 저장하는 자료구조 인터페이스

=>Table 또는 Dictionary라고도 합니다.

=>HashMap, LinkedHashMap, TreeMap 클래스에서 구현

python에서 ordered dict= >treeMap

 

6.Property클래스

=>KEYValue를 쌍으로 저장하는데 자료형이 String만 가능한 클래스

=>설정이나 메시지 저장에 많이 사용되는 클래스

 

 

7.Iterator & Enumeration

=>데이터를 순서대로 하나씩 접근할 수 있도록 해주는 포인터 : Cursor라고도 합니다.

=>자바에서는 Enumeration이 먼저 나왔고 후에 비슷한 기능을 개량한 Iterator가 추가 되었습니다.

=>우리말로 번역할 때는 반복자(c++ enumeration) 또는 열거자(python iterator) 로 변역

=>인터페이스가 구현된 컬렉션의 데이터는 for(임시변수 : 컬렉션){}구문을 이용해서 컬렉션의 모든 데이터를 임시변수에 하나씩 대입해서 {}안에서 사용할 수 있습니다.

=>Iterator의 메소드 :hasNext()(다음데이터 있느냐?) next()(다음 데이터 이동해라)

=>Enumeration의 메소드:hasMoreElements() nextElement()

 

**List

=>데이터를 순서대로 저장하는 자료구조

=>자료구조에서는 배열을 Dense List라고 하기도 합니다.

1.ArrayList(VecorArrayList Legacy버전)

=>데이터를 물리적으로 연속해서 저장하는 List

=>크기 변경이 가능(확장과 축소가 가능)

=>제너릭이 구현(인스턴스를 만들 때 데이터 1개의 자료형을 확정을 해야 합니다.)

=>인스턴스를 만들 때 자료형을 확정하지 않으면 경고가 발생하고 데이터를 가져올 때 Object타입으로 리턴되서 사용을 하고자 하면 강제 형 변환을 해야 합니다.

=> LinkedList 에 비해서 메모리 낭비가 적고 접근 속도가 빠릅니다.

=> LinkedList에 비해서 데이터를 중간에 삽입하거나 삭제하는 경우 속도가 느립니다.

LinkedList는 논리적으로 연속해서 데이터를 저장

=>주요 메소드로느 boolean add(E e), E get(int index), int size(),E remove(int index)(지울때 데이터를 return한다.), void sort(Comparator <E>) (데이터가 많을 때 ) 등이 있습니다.

 

2. LinkedList

=>데이터를 논리적으로 (다음 데이터의 참조를 기억) 연속해서 저장하는 List

=>사용하는 모든 메소드가 ArrayList와 같은데 동작 방식이 다름

 

 

배열  10 , 30 ,20 하나하나 뛰여 쓰는 구조이다. 출발점 밖에 없다.

하나 뛰면 1 두개 뛰면 2

 

 

 

 

ArrayList 아래에 비여있다. 출발점 밖에 없다.

 

40추가시 복사 안하고 아래에 추가한다.

 

 

 

 

 

DoubleLinked List python 음수 양수 가능한 것은 headtail이 있기 때문이다.

0번이 없다. 한칸 가면 10

get할 때 음수를 사용할 수 있는 것

 

 

 

메모리가 심함 : 낭비가 적을 수도 있다.( 연속적인 공간, 확장이 가능하다.)

삽인과 삭제가 용이하다.

point로 한다.

 

메모리 충돌

재시작해서 하면 메모리 문제가 있ㄷ.

빈공간이 40m이지만 30m데이터를 열 경우

배열 과 arryaList. 는 저장이 불가하다. 연속적으로 해야 하기 때문에

그래서 DOuble Linked List 가능하다. 연결이 가능하다

공간1에서 20m할당하고 공간 2에서 10m할당한다.

 

 

ORACLE 9 I ->INTERNET

ORABLE 10 G -> 초과하면 메모리 따로 할당해서 가능하다.

 

 

 

30을 지울 경우

ArrayList 30을 지울 경우 땡겨줘야 한다. 아니면 접근이 불가하다.

마지막 지우는 것은 괜찮은데 중간에것 은 문제가 생긴다.

                                   

 

 

 

 

 

 

 

 

DoubleLinked List 30을 살제 할 경우 포인터를 바꾼다.

데이터 하나하나 접근해서 가져올때 늦다.

일부분만 하면 된다.

 

연결해서 필요한 결과만 가져오면 된다.

 

지금은 디스크가 크기 때문에 arrayList를 많이 사용한다.

데이터를 그냥 쌓고 썼다 삭제 할 필요 없다.

게시판 등 읽기만 가능할 때 ArrayList 를 많이 사용한다.

웹프로그래밍은 대부분 ArrayList 사용한다. 읽기라도 빨리 읽자

Double Linked List 서버 등 추가 삭제 많이 할때

 

python은 기본을 list로 주고 queue를 준다. queue 순서대로 끄낸다. Linked List읽기 속도가 늦다.

읽기 - ArrayList

삽입 삭제 - Linked List

 

ArrayList는 데이터가 많을 수록 늦게 걸린다. 오래 걸린다.

ArrayLIST는 밀어내기 해서 늦게 걸린다.

 

실습은 정수로 했지만 실제 는  row단위로 하면 더 오래 걸릴것이다.

알고리즘을 할 경우 시간 측정하기

정밀도나 재현율 등으로 해서 알고리즘 한다.

 

 

회사 : 마이다스아이티

 

 

3.ArrayListLinkedList 작업 속도 측정

public class ListCompare {

 

       public static void main(String[] args) {

               // 정수 데이터를 저장하는 ArrayList생성

               // 제너릭에서는 기본형은 사용할 없음 - 기본형을 대체하는 Wrapper클래스 사용

               ArrayList<Integer> a1 = new ArrayList<>();// ArrayList<> 1.7부터 가증하다.

               // 데이터 삽입

               a1.add(10);

               a1.add(30);

 

               // 데이터 1 가져오기

               Integer e = a1.get(0);

               System.out.println(e);

 

               // 데이터 1 삭제

               a1.remove(0);

 

               // 데이터 전체 출력

               for (Integer imsi : a1) {

                      System.out.println(imsi);

               }

 

               // 10 30 갖는 ArrayList생성

               a1 = new ArrayList<>();// ArrayList<> 1.7부터 가증하다.

               // 데이터 삽입

               a1.add(10);

               a1.add(30);

 

               // 현재 시간 저장

               long start = System.currentTimeMillis();

               // 20이라는 데이터를 10만번 2번째 칸에 삽입

               for (int i = 0; i < 100000; i++) {

                      a1.add(1, 20);

               }

               // 현재 시간 저장

               long end = System.currentTimeMillis();

               System.out.println("a1:" + (end - start));

 

               // LinkedList 생성

               LinkedList<Integer> li = new LinkedList<>();

               // 데이터 삽입

               li.add(10);

               li.add(30);

 

               // 현재 시간 저장

               start = System.currentTimeMillis();

               // 20이라는 데이터를 10만번 2번째 칸에 삽입

               for (int i = 0; i < 100000; i++) {

                      li.add(1, 20);

               }

               // 현재 시간 저장

               end = System.currentTimeMillis();

               System.out.println("li:" + (end - start));

              

               //데이터 읽기 ================================

               // 현재 시간 저장

               start = System.currentTimeMillis();

               for (int i = 0; i < a1.size(); i++) {

                      //System.out.println(a1.get(i));

                      a1.get(i);

               }

               // 현재 시간 저장

               end = System.currentTimeMillis();

               System.out.println("a1읽기:" + (end - start));

              

              

               // 현재 시간 저장

               start = System.currentTimeMillis();

               for (int i = 0; i < li.size(); i++) {

                      //System.out.println(li.get(i));

                      li.get(i);

               }

               // 현재 시간 저장

               end = System.currentTimeMillis();

               System.out.println("li읽기:" + (end - start));

 

       }

 

}

 

4. Vector

=>ArrayList가 만들어지기 전에 ArrayList와 동일한 용도로 사용하던 자료구조인데 데이터를 수정하거나 삭제 할 떄 다른 스레드가 사용 중인지 확인하고 작업을 수행하던 클래스

=>java에서 Vector클래스는 최근에는 거의 사용을 하지 않기 때문에 중요하지 않을 수 있는데 c++하던 분들이 ArrayList라고 하지 않고 Vector라고 합니다.

vector 데이터의 모임 , scalar등 도 vector이기도 한다.

 

5.Stack

=>LIFO(Last In First Out)

=>마지막에 삽입된 데이터가 가장 먼저 출력되는 자료구조 클래스

=>데이터를 삽입하는 동작을 push라고하고 마지막 데이터를 꺼내는 동작을 pop이라고 합니다.

=>실제 사용된 곳은 메소드를 호출할 때 메소드가 저장하는 자신의 데이터 영역을 stack으로 만들고 스마트폰 등에서 화면 저장도 Stack을 사용합니다.

안드로이드는 startActivity  finish

아이폰은  push pop으로 사용한다.

겹쳐놓고 사용하는 것이 stack이라고 한다.

=> 삽입은 E push(E e), 삭제는 E pop(), 삭제하지 않고 마지막 데이러를 가져오는 E peek()

=> 제너릭이 적용되어 있어서 인스턴스를 만들 때 저장할 요소의 자료형을 설정해야 합니다.

 

네비게이션

최악이는 array

arrayListLinkedList 출발점을 끝까지 가야 한다.

최근에 데이터 사용해야 하는 것은 stack이 좋다.

public class StackTest {

 

       public static void main(String[] args) {

               //문자열 저장하는 스택 생성

               Stack <String> stack = new Stack<>();

               //데이터 저장은  push

               stack.push("안중근");

               stack.push("윤봉길");

               stack.push("김좌진");

              

               //마지막 데이터 제거하면서 가져오기

               String human = stack.pop();

               System.out.println(human);

              

               //마지막 데이터를 제거하지 않고 가져오기

               human = stack.peek();

               System.out.println(human);

               human = stack.peek();

               System.out.println(human);

       }

 

}

=>Stack size 설정한 경우에 Stack 이미 데이터가 전부 저장된 상태에서 데이터를 push하는 경우를 Stack Overflow라고 합니다.

Stack에서 데이터가 없는 상태에서 pop 하는 경우를 Stack Underflow라고 합니다.

 

 

6.Queue

=>FIFO(First In First Out)

=>먼저 삽입된 데이터를 먼저 제거하는 자료구조

=>자바에서는 인터페이스로 제공되고 여러 List클래스에 구현되어 있습니다.

=>PriorityQueue라는 우선순위 큐에도 구현되어 있습니다.

우선순위 큐는 우선순위에 따라 데이터를 정렬하고 있는 큐입니다.

=>데이터를 삽입하는 메소드는 add이고 데이터를 꺼내는 메소드는 peek poll

=>용도는 스케쥴링에 주로 이용

=>입력받은 내용을 순서대로 실행하고자 Queue 이용합니다.

인쇠

데이터를 입력하면 priorityqueue는 순서대로 한다.

데이터 입력할때 이것 사용하면 sort할 필요없다.

정렬 할 필요 없다. PriorityQueue 바꾸지 않고 Set 이용하면 중복도 처리 필요 없다.

 

0

1

가방

2

점퍼

0번과 2번 지운다. 0번과 2번 지우면 에러 난다.

0번 지우면

0

가방

1

점퍼

지울 때 마다 땡겨줘야 한다. 그다음 2로 지워면 오류 난다. 사이즈나 인덱스가 변할 수있다.

그래서 뒤에서 부터 지운다.

 

정렬 -데이터 정렬

정렬 - 트리 형태의 정렬

                                                                     정렬후

 

 

 

데이터 확정되면 quicksort등으로 만들면 되나.

데이터를 추가할 때마다 정렬할 경우 tree를 만든다. 작으면 왼쪽 크면 오른쪽

 

tree 읽는 방법    : InOrder .왼쪽 ->부모 -> 오른쪽

                        FreeOrder -> 부모

                        FirstOder -> 부모 마지막

PriorityQueueInOrder

하나씩 접근할 경우는 예측할 수 없다 . 전체 해야만 정렬이 된다.

 

이진트리 검색 이진트리 정렬

건물의 arrayList로 만들면 삽입과 삭제가 늦어서 버벅거린다.

 

실습

public class QueueTest {

 

       public static void main(String[] args) {

               //운선순위 : 데이터를 크기 순서대로 접근할 있도록 만든

               //내부적으로 데이터가 정렬된 것이 아니고 정렬된 순서대로 접근할 있는 이진 트리를 생성

               //문자열 저장하는 스택 생성

               PriorityQueue <String> pq = new PriorityQueue<>();

               //데이터 저장은  push

               pq.add("서울");

               pq.add("런던");

               pq.add("크라이스 처치");

               pq.add("블라디보스톡");

               pq.add("불산");

              

               //PriorityQueue 크기 순서대로 저장 되였다고 했는데

               //빠른 열거를 이용해서 데이터를 1 꺼내와서 출력

               //sort 되지 않았다.

               //하나씩 꺼내면 트리의 순회를 이용하지 않기 때문에 데이터가 정렬된 순서가 아닐 있음

               for(String city :pq) {

                      System.out.print(city + "\t");

               }

               System.out.print("\n");

              

               //데이터를 poll이용해서 1개씩 가져와서 출력

               //sort 순서데로 나온다.

               //pq.size()쓰면 안된다 . 5 사용해야 한다.

               //poll 제거하면서 가져오기 때문에

               //지우면서 가져올 데이터의 개수나 인덱스가 변할 있으므로 주의

               //트리의 순회를 이용하기 때문에 데이터가 정렬된 순서대로 출력  

               int len = pq.size();

               for (int i = 0; i < len; i++) { //5 고정하거나 데이터 개수를 고정해야 한다.

                      System.out.print(pq.poll() + "\t");

               }

               //     i pq. size()

               //     0 5 pq.poll()삭제씩 한다.

               //     1 4

               //     2 3

               //장바구니 경우 조심해야 한다.

       }

 

}

 

7.Deque

=>양쪽에서 삽입과 삭제가 가능한 자료구조

=>자바에서는 인터페이스 형태로 제공

=>ArrayDeque라는 클래스가 Deque인터페이스를 Implements

=>Deque를 구현한 경우는 ScrollView 계열이 전부 Deque를 이용합니다.

메모리는 위에것을 재사용한다. deque를 재사용하는 것이다. 핸드폰 넘길 때

애플의 api를 한번 확인해보라

애플은 일반 숫자면 shift사용하면 된다.

 

windows안된다.

 0 1 2 3

0 1 2 4 8

 

애플 된다. shift계산

0                   1                     2

0 << 0            1 << 0              1 << 2

 

=>삽입하거나 꺼내는 메소드 이름들에 FirstLast가 붙습니다.

어떤 종류의 데이트를 저장할 지 먼저 생각해야 한다.

ArrayDeque <String> deque = new ArrayDeque <>();

//데이터를 앞에서 저장

deque.addFirst("한국");

//데이터를 뒤에 저장

deque.addLast("미국");

deque.addLast("중국");

deque. addFirst("뉴질랜드");

 

저장 순서는 뉴질랜드 -> 한국->미국 -> 중국

 

String nation = deque.pollFirst();//뉴질랜드

nation = deque.pollLast();//중국

 

 

8. 사용자 정의 클래스의 List 정렬

=>사용자 정의클래스의 LIST가 테이블 구조

몽고 디비의 COLLECTION이라고 보면 된다.

// 선수번호(정수인데 Primary Key) ,선수이름, 타율

//primary key 정수 인것이  좋다. 속도 때문에

public class Player {

       private int num;

       private String name;

       private double hitrate;

      

       //매개변수가 없는 생성자

       public Player() {

               super();

       }

      

       //모든 필드를 매개변수로 받아서 인스턴스 필드에 대입해주는 생성자

       public Player(int num, String name, double hitrate) {

               super();

               this.num = num;

               this.name = name;

               this.hitrate = hitrate;

       }

      

       //인스턴스 필드들을 private 만들어서 인스턴스가 접근을 못합니다.

       //인스턴스가 필드들에 접근할 있도록 해주는 메소드: 접근자 메소드(getters & setters)

       public int getNum() {

               return num;

       }

 

       public void setNum(int num) {

               this.num = num;

       }

 

       public String getName() {

               return name;

       }

 

       public void setName(String name) {

               this.name = name;

       }

 

       public double getHitrate() {

               return hitrate;

       }

 

       public void setHitrate(double hitrate) {

               this.hitrate = hitrate;

       }

      

       //필드의 값을 빠르게 확인하기 위한 메소드 : 디버깅을 위한 메소드

       @Override

       public String toString() {

               return "Player [num=" + num + ", name=" + name + ", hitrate=" + hitrate + "]";

       }

}

 

 

public class ListMain {

 

       public static void main(String[] args) {

               //매개변수가 없는 생성자를 이용한 인스턴스 생성 필드값 실행

               Player player1 = new Player();

               player1.setNum(1);

               player1.setName("백인천1");

               player1.setHitrate(0.412);

              

               //매개변수가 있는 생성자를 이용한 인스턴스 생성 필드값 설정

               Player player2 = new Player(2,"이종범2",0.393);

               Player player3 = new Player(3,"이종범3",0.381);

               Player player4 = new Player(4,"이종범4",0.387);

               Player player5 = new Player(5,"이종범5",0.376);

              

               //5개의 인스턴스를 소유한 ArrayList 인스턴스 생성

               ArrayList<Player> list = new ArrayList<>();

               list.add(player1);

               list.add(player2);

               list.add(player3);

               list.add(player4);

               list.add(player5);

              

               //Player 클래스의 인스턴스 비교 인스턴스 파율의 오름차순

               //anorymose, new Comparator<Player> 쓰야 한다.

               //이것이 된다면 어떤 종류에서도 가능핟.

               Comparator<Player> comparator = new Comparator<Player>() {

 

                      @Override

                      public int compare(Player arg0, Player arg1) {

                             /*if(arg0.getHitrate() > arg1.getHitrate()) {

                                    return 1;

                             }else if(arg0.getHitrate() == arg1.getHitrate()) {

                                    return 0;

                             }else {

                                    return -1;

                             }*/

                             return arg0.getName().compareTo(arg1.getName()) * -1;

                      }

                     

               };

              

               list.sort(comparator);

               //데이터 출력

               for(Player player: list) {

                      System.out.println(player);

               }

       }

 

}

 

** Set

=>데이터를 해싱을 이용해서 저장위치를 선정하고 중복된 데이터는 저장하지 않는 자료구조

=>데이터의 저장 순서를 모르기 때문에 인덱스의 개념이 없습니다.

=>제너릭이 구현:인스턴스를 만들 요소의 자료형을 결정

1.구현된 클래스

HashSet: 저장 순서를 없는 sET

LinkedHashSet: 저장 순서를 있는 Set으로 전체를 순서래도 접근하면 저장된 순서래도 리턴

TreeSet :Comparator 인터페이스의 compareTo 멤서도를 이용해서 크기 순서대로 리턴하는 sET

 

2.주요 메소드

boolean add(E e): 데이터를 추가하고 성공 여부를 리턴 ,동일한 값의 데이터를 삽입할려고 하면 데이터를 삽입하지 않고 FALSE 리턴

boolean remove(E e): e 해당하는 데이터가 있음녀 삭제하고 결과를 리턴

int size(): 데이터 개수 리턴

데이터 1개를 접근하는 메소드는 없고 FOR(임수 변수 , set) 이용해서 데이터 전체를 접근

데이터 한개를 꺼내는 메소드가 없다.

 

3.Set사용

public class SetUse {//Set 이름 하면 에러가 난다.

 

       public static void main(String[] args) {

               // Set 인스턴스 생성 - HashSet ,LinkedHashSet , TreeSet으로 변경하면서 확인

              

               System.out.println("HashSet");

               Set<Integer> set = new HashSet<Integer>();

               // Set 데이터 추가

               set.add(100);

               set.add(300);

               set.add(200);

               set.add(500);

               set.add(400);

               // 데이터 전부 출력

               for (Integer temp : set) {

                      System.out.println(temp);

               }

              

               System.out.println("LinkedHashSet");

              

               // Set 인스턴스 생서

               Set<Integer> linkedHashSet = new LinkedHashSet<Integer>();

               // Set 데이터 추가

               linkedHashSet.add(100);

               linkedHashSet.add(300);

               linkedHashSet.add(200);

               linkedHashSet.add(500);

               linkedHashSet.add(400);

               // 데이터 전부 출력

               for (Integer temp : linkedHashSet) {

                      System.out.println(temp);

               }

              

               System.out.println("TreeSet");

              

               // Set 인스턴스 생서

               Set<Integer> treeSet = new TreeSet<Integer>();

               // Set 데이터 추가

               treeSet.add(100);

               treeSet.add(300);

               treeSet.add(200);

               treeSet.add(500);

               treeSet.add(400);

               // 데이터 전부 출력

               for (Integer temp : treeSet) {

                      System.out.println(temp);

               }

       }

 

}

 

 

4. 1-45사이의 숫자를 6 입력받아서 오름 차순 정렬해서 출력

=>데이터 6개는 하나의 이름으로 저장

=>동일한 데이터는 입력받지 않아야 합니다.

=>데이터는 오름차순 정렬

=>데이터 6개를 하나의 이름으로 저장할 있는 자료구조 :배열 ,ArrayList, LinkedList, Stack ,ProrityQueue, ArrayQueue, HashSet,LinkedHashSet, TreeSet

 

public class LottoInput {

 

       public static void main(String[] args) {

               //1-45까지의 정수를 저장할 자료구조를 생성

               TreeSet<Integer> lotto = new TreeSet<Integer>();

               //키보드로 부터 입력받기 위한 인스턴스 생성

               Scanner sc = new Scanner(System.in);

               while(lotto.size() < 6) {

                      try {

                             System.out.print("1-45까지의 중복되지 않은 숫자 :");

                             //문자를 입력해서 예외가 발생하면 catch구문이 동작하고 그러면 반복문의 시작 부분으로 돌아가서 수행

                             int su = sc.nextInt();

                            

                             if(su < 1 || su > 45) {

                                    System.out.println("1-45 사이의 숫자만 입력하세요 !!!");

                                    continue;

                             }

                            

                             //입력받은 숫자를 set 추가 : 숫자가 중복되면 false

                             boolean result = lotto.add(su);

                             if(result == false) {

                                    System.out.println("중복된 숫자는 안됩니다.");

                             }

                      }catch(Exception e) {

                             System.out.println("1-45 사이의 숫자만 입력하세요 !!!");

                             sc.nextLine();

                      }

               }

              

               //lotto 데이터 출력

               for(Integer su : lotto) {

                      System.out.print(su + "\t");

               }

               sc.close();

       }

 

}

 

 

 

 

**Map

=>key Value 쌍으로 저장하는 자료구조

=>key 중복될 없지만 Value 중복되거나 null 있습니다.

=>제너릭 미지정 자료형이 2개라서 인스턴스를 생성할 key Value자료형 2개를 설정해야 합니다.

key 특별한 경우가 아니라면 String

=>여러 종류의 데이터를 하나로 묶기 위한 용도로 주로 이용

DTO클래스의 용도와 유사

=>관계형 데이터베이스의 테이블은 DTO클래스의 List이고 No SQL Collection Map List입니다.

=>Map. Key 무한정 추가시킬 있습니다.

DTO클래스는 클래스를 만들 사용한 필드를 제외하고는 확장이 안됩니다.

 

1.Map 구현 클래스

1) HashMap(Hashtable): Key 해싱에 의해서 저장하기 때문에 key 순서를 없습니다.

2) LinkedHashMap : KEY 데이터를 저장한 순서대로 배치

3) TreeMap: key COMPAREtO메소드를 이용해서 비교한 크기 순선대로 배치

 

 

2.인스턴스 생성

HashMap<String ,실제데이터의 자료형> map = new HashMap<String ,실제데이터의 자료형>();

HashMap<String ,실제데이터의 자료형> map = new HashMap<?  ,?>();

 

3.데이터 관련 메소드

void put(key ,value): key 값에 VALUE 저장, 동일한 KEY이름을 입력하면 수정

 

Object get(key) :key 해당하는 리턴, key 없으면 null리턴

       리턴되는 데이터가 Object라서 출력하는 것이 아니고 사용할 거라면 저장할 때의 자료형으로 강제 변환해서 사용

 

Object remove(key) : key 해당하는 데이터 삭제

 

Set<Key 자료형> keySet(); Map 모든 key Set으로 리턴

 

4.Map 기본방법

public class MapUse {

       public static void main(String[] args) {

               // Map 인스턴스 생성

               HashMap<String, Object> map = new HashMap<String, Object>();

               // 데이터 저장

               map.put("baseball", "야구");

               map.put("soccer", "축구");

               map.put("volleyball", "배구");

 

               // 데이터 가져오기

               // Object obj = map.get("soccer");

               /// 출력을 때는 강제 변환이 필요없지만 다른 용도로 사용할 때는 강제 변환을 해서 가져옵니다.

               String obj = (String) map.get("soccer");

               System.out.println(obj.toUpperCase());

 

               // 없는 key 가져오기 -언어마다 다르므로 확인

               Object value = map.get("basketball");

               System.out.println(value);// java- null python 튕긴다.

 

               map.put("soccer", "발로하는 축구");

               obj = (String) map.get("soccer");

               System.out.println(obj.toUpperCase());

 

               // Map 모든 데이터를 출력 -key 이름을 사용하지 않음

              System.out.println("===============================");

               Set<String> keys = map.keySet();

               // Set 순회

               for (String key : keys) {

                      System.out.println(key + " : " + map.get(key));

               }

              

       System.out.println("=============LinkedHashMap==================");

 

               // 순서대로 하고 싶다면 LinkedHashMap으로 바꾸면 된다.

 

               // Map 인스턴스 생성

               LinkedHashMap<String, Object> map1 = new LinkedHashMap<String, Object>();

               // 데이터 저장

               map1.put("baseball", "야구");

               map1.put("soccer", "축구");

               map1.put("volleyball", "배구");

 

               // 데이터 가져오기

               // Object obj = map.get("soccer");

               /// 출력을 때는 강제 변환이 필요없지만 다른 용도로 사용할 때는 강제 변환을 해서 가져옵니다.

               String obj1 = (String) map1.get("soccer");

               System.out.println(obj1.toUpperCase());

 

               // 없는 key 가져오기 -언어마다 다르므로 확인

               Object value1 = map1.get("basketball");

               System.out.println(value1);// java- null python 튕긴다.

 

               map1.put("soccer", "발로하는 축구");

               obj1 = (String) map1.get("soccer");

               System.out.println(obj1.toUpperCase());

 

               // Map 모든 데이터를 출력 -key 이름을 사용하지 않음

              System.out.println("===============================");

               Set<String> keys1 = map1.keySet();

               // Set 순회

               for (String key : keys1) {

                      System.out.println(key + " : " + map1.get(key));

               }

       }

}

 

mac 메뉴 눌리다가 실수 가능성이 없다.

windows 여러가 나온다.

 

5. class Map 이용한 저장의 차이

public class ClassAndMap {

 

       public static void main(String[] args) {

               //번호 ,이름,타율을 저장하는 Player클래스의 인스턴스를 만들어서 데이터를 저장

              Player player = new Player(1, "이종범" , 0.393);

               //Player 코드

              

               //3개를 저장하는 map 인스턴스를 생성해서 데이터를 저장

               HashMap<String,Object> map = new HashMap<String,Object>();

               map.put("num", 2);

               map.put("name", "정호조");

               map.put("hitrate", 0.387);

              

               //서로간의 장단점이 있다.

               //대부분의 IDE에서 일반 인스턴스를 사용할 Code sense 동작

               //하나의 속석을 가져올 때는 클래스가 유용

               //map key 기억해야 합니다.

               String name = player.getName();//오타칠 가능성이 별로 없다.

               name = (String)map.get("name");

              

               //전체를 출력할 떄나 속성을 확장할 떄는 Map 유리

               //Dto클래스의 인스턴스는 속성 확장이 안됩니다.

               //dto클래스의 인스턴스는 속성을 확장할려면 클래스 구조를 변경해야 합니다.

               //테이블 설계하면 아무것도 추가 못한다. ->관계형 데이터베이스

               //map 제한이 없음

               map.put("homerun", 31);//필요하면  얼마든지 확장 있다.

              

               //전체를 출력한다면 map 훨씬 편하다.

               //DTO클래스의 인스턴스는 각각의 데이터를 하나씩 출력해야 한다면 메소드를 일일이 호출 : 반복문 사용 불가

               System.out.println(player.getNum());

               System.out.println(player.getName());

               System.out.println(player.getHitrate());

              

               //mAP 인스턴스는 KEYSET() 이용해서 반복문으로 출력 가능

               Set<String> keys = map.keySet();

               for(String key : keys) {

                      System.out.println(key + " : " + map.get(key));

               }

              

       }

 

}

 

 

6. 이차원 배열과 Map List

List List(Matrix - numpy 머신런닝) Map List(DataFrame - pandas기술통계 )

데이터가 바꿔더라도 연산의 결과등으로 사용 가능하게 해야 한다.

 

자바스크립트

angular react native

 

map 사용하면 mvc 하는데 도움이 된다.

배열에 배열 나올 같으면 고민해야 한다.

머신런닝 이름이 필요없기 때문에 배열의 배열을 사용한다.

2차원 벼열 : 제목이 없는 matrix 계산

74

83

76

32

54

68

64

74

83

 

map List 출력이나 분석

국어

영어

수학

74

83

76

32

54

68

64

74

83

합계를 구할 map list 제목을 빼고 해야 한다. .values()

 

microsoft windows list안에 list

mac map으로 한다음 다시 map list 만든다.

출력은 운영체제가 해버린다.

public class DoubleArray {

       public static void main(String[] args) {

               // 팀별 선수 명단

               ArrayList<String>  kia = new ArrayList<>();

               kia.add("최형우");

               kia.add("김주찬");

               kia.add("김선빈");

              

               ArrayList<String> dusan = new ArrayList<>();

               dusan.add("권혁");

               dusan.add("정수빈");

               dusan.add("최주환");//데이터 추가시 출력하는데 문제가 없다.

              

               //팀이름은 가지고 있지 않다

               //후에 추가한다.

               ArrayList<String> hanhwa = new ArrayList<>();

               hanhwa.add("김태군");

               hanhwa.add("이성열");

              

               //팀별 명단을 다시 List 만들기

               ArrayList<ArrayList<String>> players = new ArrayList<ArrayList<String>>();

               players.add(kia);

               players.add(dusan);

               //팀이 추가되는 경우 이름을 출력하기 위해서 출력하는 로직을 수정

               players.add(hanhwa);

              

               //데이터 출력하기

               //전체 리스트를 하나 하나의 리스트로 imsi 대입

               for(ArrayList<String> imsi: players) {

                      //imsi 데이터를 하나씩 temp 대입

                      for(String temp : imsi) {

                             System.out.print(temp + "\t");

                      }

                      System.out.println();

               }

               //팁이 명확하다.

               System.out.println("=======================");

               for(int i = 0 ; i < players.size(); i++) {

                      //팀이 추가할 경우 문제가 생긴다.

                      if(i == 0) {

                             System.out.println("기아:");

                      }else {

                             System.out.println("두산:");

                      }

                      ArrayList<String> imsi = players.get(i);

                      //imsi 데이터를 하나씩 temp 대입

                      for(String temp : imsi) {

                             System.out.print(temp + "\t");

                      }

                      System.out.println();

               }

              

               System.out.println("=======================");

               //앞에서의 문제는 List List 만들 List 특징을 같이 저장하지 못한다는데 있습니다.

               //팀이름은 문자열이고 팀의 선수 명단은 배열이라서 같이 List 저장을 못합니다.

               // 부분을 Map이나 Class 해결해야 합니다.

              

               //List 팀이륾을 갖는 Map 생성

               Map<String, Object> map1 = new HashMap<String, Object>();

               map1.put("team", "기아");

               map1.put("player", kia);

              

               Map<String, Object> map2 = new HashMap<String, Object>();

               map2.put("team", "두산");

               map2.put("player", dusan);

              

               //후에 추가하기

               Map<String, Object> map3 = new HashMap<String, Object>();

               map3.put("team", "한화");

               map3.put("player", hanhwa);

              

               //MAP lIST 생성

               ArrayList<Map<String, Object>> kbo = new ArrayList<Map<String, Object>>();

               kbo.add(map1);

               kbo.add(map2);

               kbo.add(map3);

              

               for(Map<String,Object> map : kbo) {

                      System.out.print(map.get("team") + ":");

                      ArrayList<String> p = (ArrayList<String>)map.get("player");

                      for(String temp : p) {

                             System.out.print(temp + "\t");

                      }

                      System.out.println();

               }

              

       }

}

 

7.데이터 저장

1)하나의 행은 Map이나 DTO클래스를 이용

=>mAP이나 DTO클래스는 서로 다른 자료형의 데이터를 묶어서 저장이 가능합니다.

=>lIST 배열은 동일한 종류의 데이터를 묶어줍니다.

=>lIST 배열로는 특성이 다른 데이터를 묶을 없습니다.

 

PYTHON에는 ["Hi" ,1 ] : ? =>이렇게 안한다.

list

 

 

 

 

문자와 숫자가 있을 경우 숫자로 바꾼다. 수자인데 문자로 들어오면 오류 나기 때문이다.

 

2)하나의 열을 만들 List 배열을 사용

=> 방향의 데이터는 일반적으로 동일한 자료형으로 구성되기 때문입니다.

 

**MVC(Model -View - Contrlloer)패턴

=>애플리케이션을 구현 역할 별로 분리해서 구현하도록 하는 패턴

=>애플리케이션을 역할 별로 구별해서 분리하지 않으면 어느 하나의 변경이 다른 하나의 변경에 영향을 미치게 됩니다.

유지보수가 어려워집니다

=>Model 변화가 생기더라도 View 변경하지 않아도 되도록 구현하라는 패턴

 

 

***** dto클래스를 만들때와 map일떄를 비교해라

관계형 데이터베이스는 dto클래스의 리스트

nosql MAP 리스트

MAP . 찍으면 안나와서 실수 문제

"NUM" -> "num"

대소문자 실수 많이 한다.

문자열로 경웨에는 주의 해서 봐야 한다.

 

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-12  (0) 2020.10.02
java-11  (0) 2020.10.01
java-9  (0) 2020.09.29
java-8  (0) 2020.09.28
java-7  (0) 2020.09.27

+ Recent posts