JVM 이란 

Java Virtual machine의 약자로 자바를 실행하기 위한 가상머신이라고 할 수 있다. 

 

JVM이 일하는 순서 

실행될 클래스 파일을 메모리에 로드 -> 초기화 작업수행 

메소드와 클래스 변수들을 해당 메모리영역에 배치 

클래스로드가 끝나면 JVM은 main 메소드를 찾아 지역, 객체, 참조 변수를 Stack에 쌓는다.

이제 다음 라인을 진행하면서 상황에 맞는 작업을 이어간다. (함수호출, 객체할당 등) 

 

 

JAVA 코드를 JVM 으로 실행시키는 과정을 설명하면,

자바 컴파일러에 의해 코드가 클래스 파일로 컴파일된 후 클래스로더로 해당 클래스 파일들을 업로드 시킨다. 

이후 로딩된 바이트 코드를 실행 엔진을 이용하여 해석(interpert)하여 런타임 데이터 영역에 배치시킨다. 

하지만 매번 한줄씩 해석하는데는 시간이 오래걸리기 때문에 JIT (Just In Time) 컴파일러를 이용한다. 

JIT를 사용하지 않는다면 바이트코드를 사용할때마다 interpert 해야하기 때문에 속도가 매우 느리다. 

그래서 적절한 시점에 JIT 컴파일러가 바이트 코드를 컴파일해 네이티브 코드로 캐싱해놓는다. 

여기서 컴파일한다는 것은 인터프리터처럼 한줄 단위로 컴파일 하는것이 아니라 실행하는 전체 코드를 

컴파일하고 캐시하므로 이 또한 시간이 꽤 걸린다. 하지만 한번 컴파일 된 후에는 캐싱이 되니 빠른 실행을 

보장할것이다. 한번 실행되고 말것을은 인터프리터로 처리하고 주기적으로 수행하는 것은 JIT로 컴파일 한다. 

 

이렇게 해석된 코드들은 Runtime Data Areas에 배치되어 실질적인 수행이 이루어지게 된다.

이러한 과정속에서 필요에따라 JVM은 Thread Synchronization 과 GC(Garbage Collection)같은 작업을 수행한다. 

 

 

*Runtime Data Areas : JVM이 프로그램을 수행하기 위해 OS로 부터 별도로 할당받는 메모리 공간이다. 

 

 

Runtime Data Area의 구조 

- 크게 다섯가지 영역으로 나누어 진다.

 

1. PC Register

Thread가 시작될 때 생성되며 생성되는 쓰레드마다 하나씩 존재한다.

Thread가 어떤 명령을 실행해야할지 기억하는 부부능로 현재 수행중인 JVM명령의 주소를 갖는다. 

 

 

2. JAVA Virtual Machine Stack 

프로그램 실행 과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 

저장하기 위한 영역이다. 각종 변수나 임시데이터, 스레드나 메소드의 정보를 저장한다. 메소드 호출시마다 

각각 스택프레임(메소드를 위한 공간)이 생성되고 수행이 끝나면 프레임별로 삭제한다. 

 

3. Native Method Stack 

JAVA 프로그램이 컴파일 되어 생성되는 바이트코드가 아닌 실제 수행할 수 있는 기계어로 작성된 프로그램을 

실행시키는 영역이다. 

 

4. Method Area( Class area = Stack Area) 

모든 스레드가 공유하는 메모리 영역으로 클래스, 인터페이스 메소드, 필드, Stack 변수 등의 바이트 코드를 보관한다. 

자바 프로그램은 main 메소드의 호출에서부터 흐름을 이어가기 때문이다. 

 

5. Heap

객체를 저장하는 가상메모리 공간, 프로그램상에서 런타임시 동적으로 할당하여 사용하는 영역이다. 

클래스에서 Instance를 생성하면 heap에 저장되고 new 연산자로 생성된 객체와 배열을 저장한다. 

 

 

 

 

자, 쉽게 정리하자면

 

프로그램을 start한 시점부터 생각해보자.

 

프로그램을 스타트하면 JVM은 우리가 작성한 코드들을 기계어로 바꾸기 위해 컴파일 작업을한다.

 

이렇게 컴파일된 코드들은 실행하기 위해 어딘가에 기억할 공간이 필요할것이다. 

우리가 코드를 작성할 때 메소드에 작성하듯 JVM도 실행할 코드들을 컴파일한 후 메소드 영역에 올려놓는다.

 

메소드 영역에는 우리가 작성한 클래스, 메소드, 인터페이스, 필드, Stack 변수 등을 기억하는 것이다.

 

실행할 코드들이 준비되었다면 이제 실행할 차례이다.

main 메소드를 시작으로 우리가 작성한 코드는 흐름에 따라 메소드를 호출하기도하고

연산도 이루어지고 임시로 저장되는 값도 생겨날 것이다.

 

여기서 잠깐 Stack 구조를 생각해보자, 스택은 마지막 들어온 데이터가 먼저 나간다.

그리고 Stack의 대표적인 사용예로 실행취소(Ctrl +z)와 같은 기능을 구현할때 사용한다고 한다. 

 

메소드가 실행되는 흐름을 생각해 본다면 이 구조와 비슷하다는 점을 알 수 있을것이다. 

 

고로, 이렇게 연산되는 과정에 임시 저장되는값들, 메소드가 소멸되면 사라지는 데이터들이 

Stack 영역에 저장된다고 기억하면 된다. 

 

 

Heap은 객체와 배열이 생성되는 영역이다. 

사전적인 의미에서 heap은 무엇인가를 쌓아올린 더미를 뜻한다. 

단어 자체의 의미와 비슷하게 실행되는 메소드에서 생성한 객체와 배열들을 Heap에 저장해두고 

필요할 때 찾아서 쓴다고 생각하면 될것같다. 

 

 

 

 

 

 

 

참고 

https://javarevisited.blogspot.com/2013/01/difference-between-stack-and-heap-java.html

https://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java

https://cafe.naver.com/jjdev/227

 

자주 사용하는 String 얼마나 알고있는 걸까? 

 

Java 공부를 시작했을때 객체의 생성 원리를 배웠던 적이 있다. 

 

몇 년이 지난 오늘 다시 한번 정리하는 시간을 갖는다. 

 

 

이름에서 알 수 있듯이 java의 String Pool  Java Heap Memory에 저장된 String의 pool이다. 

기본적으로 String 클래스는 자바에서 제공하는 클래스로 new 연산자와 "" 큰따옴표를 이용해 객체를 만들 수 있다. 

 

JAVA의 String Pool 

다음은 JAVA heap 공간에서 문자열이 유지되는 방법과 문자열을 작성하기 위해 다른 방법을 사용할때 

발생하는 상황들을 명확하게 설명하는 다이어그램이다. 

 

 

큰따옴표로 만들어진 문자열을 생성할때 JVM은 가장 먼저 String Pool에 같은 값이 있는 문자열이 있는지 확인한다.

있다면 해당 문자열의 레퍼런스를 리턴하고 만약 없다면 새로운 문자열을 등록한다. 

 

반면에, new 연산자를 사용하는 경우

String 클래스가 힙공간에 새로운 String 객체를 만들도록 한다. 

 

package com.journaldev.util;

public class StringPool {

    /**
     * Java String Pool example
     * @param args
     */
    public static void main(String[] args) {
        String s1 = "Cat";
        String s2 = "Cat";
        String s3 = new String("Cat");
        
        System.out.println("s1 == s2 :"+(s1==s2));
        System.out.println("s1 == s3 :"+(s1==s3));
    }

// return 
// s1 == s2 :true
// s1 == s3 :false
}

 

 

다음과 같이 정의하는 경우 String Pool 에서 몇 개의 문자열이 생성될까?

Java 인터뷰에서 String pool에 관한 질문을 받게됩니다. 예를 들어, 아래 명령문에서 몇 개의 문자열이 작성되는지;

 

String str = new String("Cat");

 

 

몇개가 생성되는지에 대한 의견은 대부분 1개 또는 2개였다. 

댓글을 읽어보니 이런 의견이 나오는건 버전의 차이 때문인것 같았다.

 

아래의 테스트를 진행해보니

결론적으론 나는 1개가 생성된다고 생각한다. 

public static void main(String[] args) {
  String a = "aaa";
  String b = "aaa";
  String c = new String("aaa");
  String d = new String("aaa");


  System.out.println(a == b); //true
  System.out.println(a == c); //false
  System.out.println(c == d); //false
  System.out.println(a.equals(b)); //true
  System.out.println(a.equals(c)); //true
  System.out.println(c.equals(d)); //true
  
  
  // intern() 메소드는 String Pool에 문자열을 확인 후 있다면 번환 
  // 아닌경우는 문자열을 풀에 등록하고 해당 문자열을 반환한다.
  
  String s1 = "Genie";
  String s2 = "Genie";
  String s3 = new String("Genie");
  String s4 = new String("Genie").intern();

  System.out.println(s1 == s2); // true
  System.out.println(s1 == s3); // false
  System.out.println(s1 == s4); // true
}

 

 

 

String만 파보아도 이렇게 재미난 이야기들이 있다.. ㅎ

 

내용에 오류가 있다면 댓글로 알려주시면 감사하겠습니다^^

 

참고 

https://www.journaldev.com/797/what-is-java-string-pool

https://www.edureka.co/blog/java-string-pool/

'Java' 카테고리의 다른 글

JAVA ) 직접 경험한 경력직 기술 면접 질문 모음  (0) 2020.07.20
JAVA 언어의 장단점  (0) 2020.07.13
JVM 그것이 알고싶다.  (0) 2020.07.12
Java Collection 총 정리~~~!!  (0) 2020.07.12
JAVA 설치 및 환경설정!  (0) 2020.07.09

Java Collection 이 데이터의 집합, 그룹을 의미하며 

JCF (Java Collections Framework)는 이러한 데이터 자료구조인 컬렉션과 이를 구현하는 클래스를 정의하는 

인터페이스를 제공한다. 

 

쉽게 이야기하면 

여러개의 데이터를 담는 방법들을 제공한다고 생각하면 된다. 

 

 

JAVA Collections Framework 상속구조는 아래와 같다. 

 

* 간단요약 
- 순서가 있는 목록인 List
- 순서 없이 데이터를 저장하는 Set
- 먼저들어온것이 먼저 나가는 Queue 
- 나중에 들어온것이 먼저 나가는 Stack 
- Key-Value 구조로 데이터를 저장하는 Map

 

 

위쪽부터 설명을 시작해보겠다. 

 

 

Queue 
- 자료의 입력과 출력을 한쪽 끝 (front, rear)으로 제한한 자료구조이다. 
- 은행에 먼저온 사람이 가장 먼저 창구에서 일을 보는 것과 같은 FIFO(First In First Out) 구조로 
- 먼저들어온 데이터가 먼저 나가는 구조이다. 

활용예시 
- 콜센터 고객 대기시간
- 프로세스 관리 
- 프린터의 인쇄 대기열

Queue 사용법

1.  Queue<String> que = new LinkedList<String>(); -- > 주로 사용함
2.  Queue<String> que = new Array<String>();
3.  Queue que = new LinkedList(); 

 

1번을 채택하여 사용한 경우 

que.offer("a");
que.offer("b");
que.offer("c");

System.out.print(que); //[a,b,c] -> que 출력
System.out.print(que.element()); //a -> 맨 앞 값 가져오기
System.out.print(que.peek()); //a -> 맨 앞 값 가져오기(element()와 동일)
System.out.print(que.poll()); //a -> 맨 앞 값 가져오고 삭제
System.out.print(que); //[b,c] 	-> que 출력


PriorityQueue
- 데이터가 먼저 나오는 일반적인 Queue와는 다르게 우선순위가 가장 높은 데이터가 가장 먼저 나온다.
- 우선순위의 결정을 도와주는 Comparable<Student>를 Implements 한 후

   compareTo 메소드를 이용해 우선순위 지정을 할 수 있다. 

간단한 사용 예시 

class Student implements Comparable<Student> {
 String name;
 int score; 

   public Genie (String name, int score) {
        this.name = name;
        this.score = score;
    }

  @Override
    public int compareTo(Student target) {
        return this.score <= target.score ? 1 : - 1;
    }

  @Override
    public String toString() {
        return "이름 : " + name + ", 점수 : " + score;
    }

} 


static PriorityQueue<Student> getPriorityQueueOfStudents() {
    PriorityQueue<Student> priorityQueue = new PriorityQueue<>();

    priorityQueue.offer(new Student("김길동", 20));
    priorityQueue.offer(new Student("Gneie", 100));
    priorityQueue.offer(new Student("홍길동", 66));

    return priorityQueue;
}


public static void main(String[] args) {
    PriorityQueue<Student> priorityQueue = getPriorityQueueOfStudents();

    // 점수가 높은 순으로 학생들 목록을 출력
    while (!priorityQueue.isEmpty())
        System.out.println(priorityQueue.poll());
}


결과 -- 
이름 : Genie, 점수 : 100
이름 : 홍길동, 점수 : 66
이름 : 김길동, 점수 : 20


List 
- List 는 배열이 가지고 있는 Index라는 장점을 버리는 대신 빈틈없는 데이터 적재라는 장점을 가졌다. 
- 같은 값을 가진 데이터를 중복으로 저장할 수 있으며  기존의 배열은 크기를 지정하고 사용해야하는 반면 List는 add와 remove함수를 통해 융통성 있는 크기 조절이 가능하다. 

* ArrayList와 List의 차이 
- ArrayList 는 클래스이고 List는 인터페이스라는 점에서 차이가 있다. 
- 클래스인 ArrayList 를 사용해서 생성 시점에 List 외에도 RandomAccess, Serializable인터페이스 등을 구현할 수 있다. 

쉽게 말하면 
List는 인터페이스이므로 도형에 비유할 수 있고 
ArrayList는 클래스이므로 정사각형이라고 비유할 수 있다. 



LinkedList 
- 저장된 데이터간 연결(link)을 통해서 리스트로 구현된 객체이다.

- 다음 데이터의 위치 정보만을 가지고 있기  때문에 순차접근만 가능하다.  
- 데이터 추가/삭제를 수행하는 경우 위치정보의 수정만으로 가능하기 때문에 성능이 좋다.
- index를 가진 배열을 보면 중간에 데이터가 추가되는 경우

  기존에 있던 데이터들의 인덱싱이 다시 변경되어야하는 반면 
  LinkedList는 앞 데이터의 Link 값만 변경해주면 되기 때문에 빠르다고 생각하면 된다. 

//선언 
LinkedList<Integer> list = new LinkedList<Integer>();

//사용 
list.addFirst(1);//가장 앞에 데이터 추가
list.addLast(2);//가장 뒤에 데이터 추가
list.add(3);//데이터 추가
list.add(1, 4);//index 1뒤에 데이터 4 추가

//값 출력 
Iterator<Integer> iter = list.iterator(); 
while(iter.hasNext()){
    System.out.println(iter.next());
}

Stack 
- 제이터의 입력과 출력을 한 곳(방향)으로 제한한 자료구조.
- 가장 마지막에 들어온 데이터가 가장 먼저 나가는 구조이다. LIFO (Last In First Out)

활용예시
- 웹브라우저의 방문기록 뒤로가기 : 가장 나중에 열린 페이지부터 다시 보여준다. 
- 역순 문자열 만들기 
- 실행취소(undo) : 우리가 ctrl+z 를 누르면 가장 마지막에 실행된게 취소되는 모습과 같다. 
- 수식의 괄호검사 : 연산자 우선 순위 표현을 위한 괄호 검사에 사용한다. 


Vector
- Vector는 ArrayList와 동일한 내부구조를 가지고 있다. Vector 객체를 생성하기 위해선 저장할 타입을 지정해야한다. 
- ArrayList와의 대표적인 차이점은 Vector 클래스는 동기회된 (syschronized)  메서드로 구성되어있다는 점으로 

  멀티 스레트 환경에서 안전하게 객체를 추가, 삭제할 수 있다. ( Thread Safe) 
  하지만 동기화 되어있기때문에 데이터를 추가, 삭제하는 과정은 ArrayList보다 느리다. 


ArrayList 

- 데이터가 순서대로 저장되며 add, remove 함수를 통해 유동적인 데이터의 추가, 삭제가 가능하다.
- 내부에서 처음 설정한 저장용량(capacity)의 크기를 넘어선 객체가 들어오면 배열의 크기를 1.5배 증가시킨다.
- index로 관리되어 있어 객체 검색과 맨 마지막에 객체를 추가하는 경우 좋은 성능을 발휘한다. 

중간에 저장되어있는 데이터를 삭제하는 경우, 제거한 데이터부터 마지막 데이터까지 1칸씩 앞으로 이동하게되고  
중간에 데이터를 추가하는 경우, 추가한 데이터부터 마지막 데이터까지 1칸씩 뒤로 이동해야한다. 

그렇기 때문에 잦은 데이터의 추가, 삭제가 발생해야하는 경우라면 LinkedList를 사용하는것이 좋다. 

 

선언방법
ArrayList<String> mylist = new ArrayList<String>();

 

Set
앞서 다루었던 List 클래스를 기반으로 한 ArrayList, LinkedList와 사용방법은 매우 유사하다. 
하지만 List와는 다르게 데이터를 중복해서 저장할 수 없고 검색에 있어서는 우월한 속도를 자랑한다.
또 index로 관리 되지 않기 때문에 저장 순서가 보장되지 않는다. 
수학에서 말하는 집합과 비슷한 내용이라고 생각하면 된다. 

사용예시
A사이트에서는 출석체크 이벤트가 진행중이다.

사이트에 접속하면 자동으로 출석체크가 되는데,
한명의 사용자가 여러번 방문하는 경우 출석체크가 여러번 저장되게 된다.

> 이렇게 데이터를 중복해서 저장 할 필요가 없는 경우 Set 구조로 가져간다. 



HashSet
- Set 컬렉션에서 가장 많이 사용되는 클래스 중 하나이다. 
- 이유는 해시 알고리즘을 사용하여 검색속도가 매우 빠르기 때문이다. 

 

사용예시 

동명이인은 많지만 주민등록번호는 사람마다 가지고 있는 고유한 번호이다.  

그렇다면 주민번호를 보면 같은 사람인지 판별이 가능하게 된다.
그런데 Set에 단순히 Person 클래스만 넘겨주면 중복여부를 판별하지 못한다. 

그래서 사용하는  메소드가 바로 equals()과 hashcode()이다.

 

1. equals(Object o)
두 객체(현재 이 객체와 인자로 넘어온 객체 o)가 같다는 것을 알려주려면  true를 리턴한다.

2. hashCode()
equals에서 true를 반환했다면 hashCode는 두 객체에서 항상 같은 값을 반환해야합니다. 
만일 equals에서 false를 반환했다면 hashCode 역시 다르게 반환하는 것이 좋습니다.

class Person{
	String name; //이름
	int residentNumber; //주민번호
	
	public Person(String name,int residentNumber){
		this.name=name;
		this.residentNumber=residentNumber;
	}

	@Override
	public int hashCode(){
		/* Objects.hash 메소드로 residentNumber의 해쉬값 반환 */
		return Objects.hash(residentNumber);
	}
	
	@Override
	public boolean equals(Object o){
		/* 주민 번호가 같은 Person은 true 반환 */
		Person p=(Person)o;
		return p.residentNumber==this.residentNumber;
	}
}


// 이제 Set에 넣고 확인해보면 

public static void main(String[] args){
	
	Set hashSet=new HashSet();
	hashSet.add(new Person("김길동", 1111));
	hashSet.add(new Person("김기동", 1111));
	hashSet.add(new Person("강감찬", 2222));

	
	Iterator it=hashSet.iterator();
	while(it.hasNext()){
		Person p=it.next();
		System.out.println(p.name+"/"+p.residentNumber);
	}
}


//결과 --- 
//김길동/1111
//강감찬/2222

 


​ThreeSet
-이진탐색트리(BinarySearch Tree)의 형태로 데이터를 저장하는 컬렉션이다. 
- 따라서 데이터의 추가, 삭제에는 시간이 걸리지만, 검색과 정렬 기능은 뛰어나다는 장점이 있다. 
- 다른 Set 구조와 마찬가지로 중복된 데이터의 저장을 허용하지 않고 저장순서를 유지하지 않는다. 
- 다른 점은 데이터가 정렬된 위치에 저장된다는 점이다. 

사용예시를 보면 아래와 같다.

TreeSet<Integer> myset = new TreeSet<>();
myset.add(1);
myset.add(2);
myset.add(100);
myset.add(200);
myset.add(300);

System.out.println(myset); //TreeSet 객체 전부를 반환
System.out.println(myset.subSet(1,100)); // 1 이상 100미만 객체 반환
System.out.println(myset.headSet(100)); // 100보다 작은 객체 반환
System.out.println(myset.contains(777)); // 777 있는지 없는지에따라 true/false
System.out.println(myset.tailSet(200)); // 200 이상의 객체 반환

 

* 사용한 함수 설명 
subSet(E fromElement, E toElement)
 - fromElement 이상 toElement 미만의 객체를 반환

headSet(E toElement)
 - toElement보다 작은 객체를 반환

contains(Object o)
- Object를 포함하는 객체를 반환

tailSet(E fromElement)
- fromElement 이상의 객체를 반환

 


HashSet과 TreeSet비교
HashSet, TreeSet 모두 중복을 허용하지 않고 순서가 없는 컬렉션이다.

1. 구현방식
 - HashSet은 해싱을 이용해 구현
 - TreeSet은 이진탐색트리를 이용해 구현

2. 속도
 - HashSet > TreeSet
 - 해싱이 이진탐색트리보다 빠름

3. 정렬 기능
 - HashSet < TreeSet
 - 이진탐색트리를 이용했기 때문에 데이터 정렬이 가능

 

 


SortedSet 
- 인터페이스로  Set요소의 자연 순서  또는 생성시 Comparator제공된 순서에 따라 정렬 된 요소를

  오름차순으로 유지하는 요소이다.
- SortedSet은 보관하는 객체의 순서가 의미가 있을 때,중복된 객체를 허용하지 않을 때 사용하면 좋다.

- 객체를 순서대로 Iteration하기 위해서는 다음 2가지중 하나는 반드시 필요하다.


1. SortedSet에 포함되는 객체가 Comparable인터페이스를 구현한 객체이거나 
2. Comparator인터페이스를 구현한 객체이어야한다.

 

List<String> alpa= Arrays.asList("B", "A", "D", "F", "G", );
SortedSet<String> alpaSet = new TreeSet<>(alpa);


위와같이 5개의 알파벳문자로 TreeSet 객체를 생성하면 TreeSet은 원소들을 정렬된 상태인 
A B D F G 순서로 보관하고 있는다.

 

 

* 특정범위에 접근하는 방법 

// 첫번째 first,  마지막 last
System.out.println(alpaSet.first());
System.out.println(alpaSet.last());

// 가장 작은 원소부터 특정값까지 범위 접근은 headSet 메소드를 사용한다. 
Set<String> headSet = alpaSet.headSet("D");
System.out.println("headSet: " + headSet);
// headSet: [A, B]

// 특정 데이터로부터 가장큰 데이터까지의 접근은 tailSet 메소드를 사용한다. 
Set<String> headSet = alpaSet.tailSet("D");
System.out.println("headSet: " + headSet);
// headSet: [F, G]

// D보다 크거나 같고 G보다 작은 범위의 접근은 subSet을 사용한다.
Set<String> headSet = alpaSet.subSet("D","G");
System.out.println("headSet: " + headSet);
// headSet: [D, F]

 

 


Map
- Map 컬렉션은 Key와 value로 구성되어있다. 

- 키와 값은 모두 객체이며 키는 중복될 수 없고 값은 중복으로 저장 가능하다.
- 만약 이미 존재하는 키값으로 새로운 데이터를 추가하면 기존의 데이터는 사라지고 새로운 값으로 대체된다. 
  * Map<key 자료형, value자료형> 

- 키와 값의 타입은 기본 타입(byte, short, int, float, double, boolean, char)을 사용할 수 없고 

  클래스 및 인터페이스 타입만 가능하다.

 


HashTable

- Hashtable은 HashMap과 동일한 사용법을 갖는데 HashMap과 차이점으로는 동기화 부분이다.
- HashTable은 동기화된(Synchronized) 메서드로 구성되어 있기 때문에 멀티 스레드 환경에서는

  동시에 메서드를 실행할 수 없다. 
- 하나의 스레드가 작업이 완료되어 메서드에서 빠져나가야 다른 스레드가 해당 메서드를 실행할 수 있다. 
- 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제를 할 수 있기 때문에 스레드에 안전(thread safe)하다고 말한다.

선언방법 
Map<String, String> map = new HashTable<>();


HashMap
- Map 인터페이스를 구현한 대표적으로 많이 사용되는 컬렉션이다. 
- JDK 1.2부터 제공된 HashMap 클래스는 해시 알고리즘(hash algorithm)을 사용하여 검색 속도가 매우 빠르다.

선언방법 
Map<String, String> map = new HashMap<>();


SortedMap 
SortedMap은 key의 값이 Integer, Double 등과 같이 비교 가능한(Comparable) 타입이거나, 
SortedMap을 생성하는 시기에 별도의 Comparator를 등록해서 정렬할 수 있다.

정리하자면, Map의 Key가 정렬되기 위해서는
-  Key가 Comparable 인터페이스를 구현한다.
-  Map 인스턴스 생성 단계에 Comparator 구현객체를 등록한다.

이때 유지되는 Key 순서는 Map이 지니는 entrySet(), entrySet(), values() 메소드를 통해

생성되는 Collection에도 반영된다. 


Comparator comparator()
- SortedMap에 등록된 Comparator가 있으면 해당 인스턴스를 리턴하고, 별도로 등록된게 없으면 null을 리턴합니다.
K firstKey()
- 첫번째 Key를 리턴합니다. 오름차순의 경우 가장 작은 값(lowest)을 리턴합니다.
K lastKey()
- 마지막 Key를 리턴합니다. 오름차순의 경우 가장 큰 값(highest)을 리턴합니다.
SortedMap headMap(K toKey)
- 인자로 받은 toKey 보다 작은 Key들을 가지고서 부분적인 Map을 리턴합니다.
sortedMap tailMap(K fromKey)
- 인자로 받은 fromKey 보다 큰 Key들을 가지고서 부분적인 Map을 리턴합니다.

 

ThreeMap
- TreeMap 클래스는 키와 값을 한 쌍으로 하는 데이터를 이진 검색 트리(binary search tree)의 형태로 저장한다. 
- 이진 검색 트리는 데이터를 추가하거나 제거하는 등의 기본 동작 시간이 매우 빠르다.
- JDK 1.2부터 제공된 TreeMap 클래스는 NavigableMap 인터페이스를 기존의 이진 검색 트리의 성능을 향상시킨

  레드-블랙 트리(Red-Black tree)로 구현한다.

선언방법 
TreeMap<Integer, String> tm = new TreeMap<Integer, String>();
 

 

 

 

 

 

우선 자바를 다운로드 받기위해 

 

자바를 제공하는 사이트로 이동 

 

https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

 

 

본인 컴퓨터 환경에 맞는 파일로 다운로드 해주세요!. 

 

 

 

 

 

exe 파일을 다운로드 받았다면 실행시켜줍니다. 

 

다음 버튼을 계속 눌러주면 다운로드 끝!

 

 

*** 설치 경로는 확인해두세용!! 

 

 

 

설치가 끝났다면 설치할때 지정했던 경로로

 

(기본설정 폴더는  - C:\Program Files\Java) 경로로 이동해서 잘 설치가 되었는지 확인해주세요. 

 

 

 

 

이제 환경변수를 설정해보겠습니다. 

 

작업 표시줄을 보면 "검색하려면 여기에 입력하십시오"란이 있죠? 

 

거기에 sysdm.cpl 명령어를 입력하고 엔터! 

 

 

 

 

 

시스템 속성창이 나오면 "고급" 탭으로 이동합니다. 

 

 

 

 

환경 변수를 클릭해서 들어가주세요. 

 

 

 

아래 새로 만들기 버튼 클릭! 

 

 

 자바를 설치한 디렉토리로 이동 후 반드시 JDK폴더까지 선택 후 확인 버튼을 눌러주세요!

 

 

 

그 다음 Path를 찾아서 편집을 눌러주세요~~ 

 

 

 

 

 

 

 

 

새로 만들기를 통해 %JAVA_HOME%\bin 을 입력해주시고, 

 

해당 변수를 위로 이동 버튼을 통해 가장 위로 올려주세요.

 

등록했다면 확인 버튼을 누르고 ~~ 편집창을 빠져나오시면 됩니다.

 

 

자 이제 Java SE가 제대로 설치되었는지, 환경 변수가 제대로 잡혔는지 확인하기 위해

 

CMD 창을 열어볼건데요 

 

작업 표시줄을 보면 "검색하려면 여기에 입력하십시오"란이 있죠?

 

거기에 cmd 를 입력하고 엔터! 

 

 

 

 

검은 창이 열리면

 

java -version 명령어를 입력하고 엔터 

 

아래처럼 버전이 나오면 설치는 끝~!  

 

+ Recent posts