🟦 기본 환경: IDE: IntelliJ, Language: Java

 

 

SpringBoot의 MainApplication에서 다음 Source Code를 실행할 경우,

1
2
3
4
5
6
7
@GetMapping("/")
    public List<Item> list() {
        List<Item> items = itemStoryService.itemList();
        System.out.println(items)
        return items;
    }
 
 
 

🚨 다음과 같은 Error 발생

java.lang.StackOverflowError: null

 

 

발생 원인

@Data: 클래스의 Getter, Setter, equals(), hashCode(), toString() 등의 메서드를 자동으로 생성

클래스 내의 모든 필드를 포함한 문자열을 생성하기 위해 각 필드의 toString() 메서드를 호출

→ 클래스 내에 상호참조되는 관계가 있을 경우, 한 객체의 toString() 메서드에서 다른 객체의 toString() 메서드를 호출

→ 그 객체에서 다시 처음의 객체의 toString() 메서드를 호출(상호 참조 관계이므로)

→ 무한한 재귀 호출로 이어져 StackOverflowError가 발생

 

 

해결 방법

1. Entity의 @Data를 @Getter, @Setter로 수정

2. @ToString(exclude = "재 호출하는 entity 이름") 옵션 추가

 

 

정리

println() → valueOf() → toString() 호출

EntityA의 모든 필드에 대해 문자열화를 위해 필드로 선언된 EntityB의 toString 호출

→ EntityB의 toString()는 EntityB의 모든 필드에 대해 문자열화를 위해 필드로 선언된 EntityA의 toString 호출

→ 무한 반복

 

 

 

참고 자료

 

20. [JPA] lombok 사용 시 주의사항

엔티티 클래스에 lombok을 사용하면 StackOverflowError 오류가 발생할 수 있다. 다음과 같은 엔티티 연관 관계가 있다고 하자.12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535

lng1982.tistory.com

 

이 글은 김영한의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 수강하며 정리한 글입니다.

 

 

🟦 기본 환경: IDE: IntelliJ, Language: Java

 

 

1차 cache

: EntityManager가 관리하는 영속성 컨텍스트(Persistence Context) 내부에 있는 첫 번째 캐시

 

비영속상태

: Entity Manager에 의해 관리되지 않는 상태

 

영속상태

: Entity Manager에 의해 관리되는 상태

 

 

⭐ 영속성 컨텍스트에 저장 ≠ DB에 저장

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            // 비영속: Entity Manager와 무관
            Member member = new Member();
            member.setId(100L);
            member.setName("HelloJPA");
 
            // 영속
            System.out.println("BEFORE");
            em.persist(member); // 1차 cache 저장
            System.out.println("AFTER");
 
            tx.commit(); // commit 후, DB 저장
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
10
11
BEFORE
AFTER
Hibernate: 
    /* insert jpa_basic.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
 
 

⭐ BEFORE 출력 em.persist → AFTER 출력 → DB 저장(insert query)

 

 

1차 CACHE 조회(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            // 비영속: Entity Manager와 무관
            Member member = new Member();
            member.setId(101L);
            member.setName("HelloJPA");
 
            // 영속
            em.persist(member); // 1차 cache 저장
 
            Member findMember = em.find(Member.class, 101L);
            // 1차 cache에 저장된 동일한 PK로 값을 조회하므로 DB에 select을 사용하지 않고도 findMember가 가능
            System.out.println("findMember.id: " + findMember.getId());
            System.out.println("findMember.name: " + findMember.getName());
 
            tx.commit(); // commit 후, DB 저장
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
10
11
findMember.id: 101
findMember.name: HelloJPA
Hibernate: 
    /* insert jpa_basic.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
 
 

⭐ DB에 insert query 전 데이터 조회 가능

: persist ▶ persistence context의 1차 cache에 저장 ▶ find()  가장 먼저 1차 캐시 검색

: Main App 실행 시, persist()를 통해 1차 캐시에 저장된 값과 find()로 조회하고자하는 대상(매개변수 PK)이 같다면 같은 transaction 안에서 같은 영속성 컨텍스트로 관리되는 상태이므로 1차 캐시에서 조회할 수 있음

 

 

1차 CACHE 조회(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            Member findMember = em.find(Member.class, 101L);
            Member findMember = em.find(Member.class, 101L);
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.name as name2_0_0_ 
    from
        Member member0_ 
    where
        member0_.id=?
 
 
 

⭐ 1차 캐시가 빈 상태에서 같은 대상을 조회할 경우, select query가 1개밖에 존재하지 않음

: find() ▶ 1차 캐시 조회 ▶ DB 조회 ▶1차 캐시에 저장

: member1 - 1차 캐시에 조회할 데이터가 없으므로 DB로 select query 실행

: member2 - member1 조회한 데이터 값이 1차 캐시에 저장되었으므로 1차 캐시에서 데이터 조회(select query 발생 X)

 

 

 

참고 자료

 

JPA - 영속성(persistence란) [+1차 캐시]

영속성 Spring JPA 로고를 보면 영속성(persistence)라는 단어가 크게 그려져 있습니다. 그만큼, 영속성 없이 Spring JPA를 얘기하기 힘듭니다. 영속성은 쉽게 말하면 지속을 의미합니다. 더 자세히 풀자

jaehoney.tistory.com

 

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

[JPA] @PrePersist  (0) 2023.06.25
[JPA] JOIN Null값 처리  (0) 2023.06.20
[JPA_Basic] JPA persist, find, remove, update  (1) 2023.06.15
[SpringBoot_JPA_1] @PathVariable  (0) 2023.06.03
[SpringBoot_JPA_1] TypedQuery  (0) 2023.06.02

이 글은 김영한의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 수강하며 정리한 글입니다.

 

 

🟦 기본 환경: IDE: IntelliJ, Language: Java

 

 

Persistence.xml

: JPA가 접근하고자하는 DB에 대해 필요한 설정 정보들을 기술해둔 파일

→ JPA는 이 파일의 설정 정보를 바탕으로 접근할 DB의 정보를 가져 올 수 있음

 

EntityManagerFactory

: EntityManager(Entity를 관리하고 DB 관련 작업을 수행 함)를 생성

: DB 당 1개 생성

 

EntityManager

: 특정 작업을 위해 데이터베이스에 액세스 하는 역할

: DB에 저장되는 transaction 단위마다 생성

 

EntityTransaction

: 데이터베이스 트랜잭션을 관리하기 위한 인터페이스로, 트랜잭션의 시작, 커밋, 롤백 등의 작업을 수행하는 메서드를 제공

: JPA의 모든 데이터 변경은 transaction 안에서 실행

 

Transaction Structure

: commit과 rollback이 try-catch 구조를 이뤄야하며, 반드시 Entity Manager가 종료될 수 있도록 finally 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                // 실행하고자하는 코드
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

 

JPA - 회원 가입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                Member member = new Member();
                member.setId(2L);
                member.setName("HelloB");
                em.persist(member);
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

 

JPA - 회원 조회

: 조회의 경우, commit이 필요없으므로 try-catch 구문 불필요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                Member findMember = em.find(Member.class, 1L);
                // 1번째 parameter: Entity Class, 2번째 parameter: PK
                System.out.println("id: " + findMember.getId());
                System.out.println("name: " + findMember.getName());
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

 

JPA - 회원 삭제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                Member findMember = em.find(Member.class, 1L);
                em.remove(findMember);
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

 

JPA - 회원 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                Member findMember = em.find(Member.class, 1L);
                findMember.setName("HelloJPA");
 
                tx.commit(); // update를 작성하지 않아도 findMember 내용의 변경이 있을 경우, JPA 자동 update query 생성
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

 

 + JPA - 전체 회원 조회

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        // EntityManagerFactory: Application Loading 시점에 1개만 생성(DB당 1개)
 
        EntityManager em = emf.createEntityManager();
        // EntityManager: DB에 저장되는 transaction 단위마다 생성
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
                List<Member> result = em.createQuery("select m from Member as m", Member.class)
                        .setFirstResult(0)
                        .setMaxResults(5)
                        .getResultList();
 
                for(Member member : result) {
                    System.out.println("member.name: " + member.getName());
            }
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

createQuery

: EntityManager(em) 객체를 사용하여 쿼리를 생성하는 메서드

: JPA의 객체지향 쿼리 언어인 JPQL을 사용, Entity Class 사용

 

setFirstResult

: 조회 결과 중에서 첫 번째로 가져올 레코드의 인덱스를 설정

 

setMaxResults

: 최대로 가져올 결과 레코드 수를 설정

 

getResultList

: 쿼리를 실행하고 결과를 리스트 형태로 반환

 

 

 

참고 자료

 

JPA 작동 메커니즘

JAVA의 ORM 표준 : JPA 이전 포스팅에서 SQL 중심적인 개발의 문제점을 살펴보고 해결방법으로 JAVA의 ORM 표준인 JPA를 가볍게 언급해보았다. 그렇다면, JAVA에서는 JPA을 어떻게 지원하고 개발자들이 지

velog.io

 

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

[JPA] JOIN Null값 처리  (0) 2023.06.20
[SpringBoot_JPA_Basic] JPA 1차 cache  (0) 2023.06.16
[SpringBoot_JPA_1] @PathVariable  (0) 2023.06.03
[SpringBoot_JPA_1] TypedQuery  (0) 2023.06.02
[SpringBoot_JPA_1] @NoArgsConstructor  (1) 2023.05.30

🟦 기본 환경: IDE: IntelliJ, Language: Java

 

 

IntelliJ + Gradle 환경에서 프로젝트 import 후, 실행 시 다음과 같은 Error 발생

🚨 finished with non-zero exit value 1

 

 

해결 방법

1. Project import 후 첫 시작 시,

Eclipse or Gradle 중 Eclipse 선택

→ 이미, Gradle을 선택한 경우, project import 과정을 처음부터 다시 시작

 

2. Settings 수정

Settings → Build, Execution, Deployment → Build Tools → Gradle

 - Build and run

: Build and run using: Gradle → IntelliJ IDEA 변경

: Run tests using: Gradle → IntelliJ IDEA 변경

 - Gradle

: Use Gradle from: Wrapper → Wrapper task

 

(Optional: IntelliJ Community Version)

3. Gradle.build 수정

dependencies 삭제

: providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'

 

 

 

참고 자료

📚 프로젝트 리틀 나인 팀원분들

 

intellij 실행 시 finished with non-zero exit value 1 오류

intellij, Gradle 환경에서 프로젝트를 첫 실행 할 때 아래와 같은 오류가 발생하는 경우가 있습니다. Execution failed for task ':DemoSpringApplication.main()'. > Process 'command 'JDK경로/bin/java.exe'' finished with non-zero

yjh5369.tistory.com

 

이 글은 남궁성의 정석코딩 [자바의정석-기초편] 수강하며 정리한 글입니다.

 

 

🟣 기본 환경: IDE: Eclipse, Language: Java

 

 

 

Set: 순서X, 중복X

TreeSet: 이진 검색 트리(Binary Search Tree*)를 활용하여 자료 정렬

* Binary Search Tree: 조상 노드의 왼쪽에는 조상 노드보다 작은 값, 오른쪽에는 큰 값을 저장하는 이진트리, 첫 번째로 저장하는 값이 최고 조상 노드(=루트)가 됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O
        // Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

Set.HashSet: 순서(인덱스)X, 중복X*

* 값이 추가될 때마다, hashcode()->equals() 비교하여 모두 true일 경우, 동일 객체로 판단

 

합집합, 교집합, 차집합

* 계산 시, 초기값을 변경하지 말고 새로운 객체 생성(향후 계산 시 문제 발생)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import java.util.HashSet;
import java.util.Iterator;
 
public class Ex11_12 {
 
    public static void main(String[] args) {
        HashSet<Integer> setA    = new HashSet<>();
        HashSet<Integer> setB     = new HashSet<>();
        HashSet<Integer> setHab = new HashSet<>();
        HashSet<Integer> setKyo = new HashSet<>();
        HashSet<Integer> setCha = new HashSet<>();
        
        setA.add(1);
        setA.add(2);
        setA.add(3);
        setA.add(4);
        setA.add(5);
        System.out.println("setA: "+setA);
        
        setB.add(4);
        setB.add(5);
        setB.add(6);
        setB.add(7);
        setB.add(8);
        System.out.println("SetB: "+setB);
        
        // 합집합
        Iterator<Integer> it = setA.iterator(); // iterator는 일회용이므로 사용시마다 생성
        while(it.hasNext()) { // 읽어올 다음 요소가 있는 동안
            setHab.add(it.next()); // 요소 하나 꺼내오기
        }
        it = setB.iterator(); // iterator는 일회용이므로 사용시마다 생성
        while(it.hasNext()) {
            setHab.add(it.next());
        }
        System.out.println("setHab: "+setHab);
 
        // setA와 setB를 직접 건드리는 것은 차후 계산에 영향을 미치게되므로 새로운 참조변수 생성하여 진행
//        setA.addAll(setB); // 합집합, setB 모든 요소 추가(중복 제외)
//        System.out.println("Hab: "+setA);
 
        
        // 교집합
        Iterator<Integer> it2 = setA.iterator(); // iterator는 사용시마다 생성
        it2 = setB.iterator();
        while(it2.hasNext()) { 
            Integer tmp = it2.next(); 
            if(setA.contains(tmp)) {setKyo.add(tmp);}
        }
        System.out.println("setKyo: "+setKyo);
 
//        setA.retainAll(setB); // 공통된 요소만 남기고 삭제
//        System.out.println("Kyo: "+setA);
 
                
        // 차집합
        Iterator<Integer> it3 = setA.iterator();
        it3 = setA.iterator();
        while(it3.hasNext()) {
            Integer tmp = it3.next();
            if(!setB.contains(tmp)) {setCha.add(tmp);}
            // 만일 setB가 tmp(setA의 각 요소)를 포함하고 있지 않다면 setCha에 추가
        }        
        
        System.out.println("setCha: "+setCha);
        
//        System.out.println(setA);
//        System.out.println(setB);
//        setA.removeAll(setB); // 차집합, 공통된 요소 모두 제거
//        System.out.println("Cha: "+setA);
    }
}
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O
        // Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

treeSet: 이진탐색정렬 -> 정렬기준 필요, 중복X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.util.*;
 
public class Ex11_13 {
    public static void main(String[] args) {
        // TreeSet(): 범위 검색 유리, 자동 정렬, 중복X
        Set<Object> treeSet = new TreeSet<>(new TestComp());
        // 정렬기준으 2개일 때는, TreeSet(정렬기준)이 우선 적용됨
        Set<Object> treeSet2 = new TreeSet<>();
 
        // HashSet: 정렬X
        Set<Object> hashSet3 = new HashSet<>();
 
        treeSet2.add(1);
        treeSet2.add(2);
        treeSet2.add(3);
        treeSet2.add(3); // 중복으로 treeSet에 저장X
        
        // Test class에서는 comparable을 구현하고 있지 않으므로 set.add를 할 경우 오류 발생
        for(int i=0; treeSet.size()<6; i++) {
            int num = (int)(Math.random()*45)+1;
//            treeSet.add(num); // AutoBoxing
            treeSet.add(Integer.valueOf(num));
            treeSet.add(new Test());
            // ClassCastException(형변환 예외): class Test cannot be cast to class java.lang.Integer)
            // set.add()는 이진탐색트리를 통해서 비교하면서 add()를 수행하는데 비교 기준이 없음
            // 비교기준을 만들어 treeSet 정렬기준에 대입: new TreeSet<>(new TestComp())
            hashSet3.add(num);            
        }
        
        treeSet.add(new Test());
        treeSet.add(new Test());
        treeSet.add(new Test());
        
        System.out.println("TreeSet: "+treeSet);
        System.out.println("TreeSet2: "+treeSet2);
        System.out.println("HashSet: "+hashSet3);
    }
}
 
class Test implements Comparable<Object> {
// Test class와 달리 스스로 비교 기준을 마련할 경우, treeSet 사용가능(예: Integer)
// treeSet 객체 생성 시 따로 비교기준 입력 필요 X: new TreeSet<>()
    @Override
    public int compareTo(Object o) {
        return 1;
    }    
}
 
class Test2 {}
// 비교 기준을 따로 구현하지 않았는데 Test2를 객체로하여 treeSet을 이용할 경우, Exception 발생
 
class TestComp implements Comparator<Object> {
// new Test2() 객체를 treeSet으로 구현하기 위한 비교 기준 마련
    @Override
    public int compare(Object o1, Object o2) {
        return -1// return을 0으로 했을 경우, o1, o2가 같다고 취급됨
    }
}
 
 
 

 

subSet()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.*;
 
public class Ex11_14 {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>();
        
        String from = "b";
        String to    = "d";
        String to2  = "e";
        
        set.add("abc");
        set.add("apple");
        set.add("bcd");
        set.add("banana");
        set.add("cde");
        set.add("Car"); // 대문자가 가장 먼저 정렬
        set.add("car");
        set.add("document");
        set.add("drop");
        set.add("department");
        set.add("element");
        set.add("eating");
        set.add("frequence");
        set.add("flower");
        set.add("generic");
        set.add("grow");
        
        System.out.println("set: "+set);
        System.out.println("range search: "+set.subSet(from, to));
        // 대문자 미포함, to 미포함
        System.out.println("range search2: "+set.subSet(from, to2));        
        System.out.println("range search2: "+set.subSet(from, to+"zzz"));
        // to+"zzz"="dzzz"        
    }
}
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.*;
 
public class Ex11_15 {
    public static void main(String[] args) {
        // set: 중복 X, 순서 X
        // treeSet: 중복 X, 순서 O (이진탐색트리)
        TreeSet<Integer> set = new TreeSet<>();
        int[] scope = {80952045105550307510060};
        
        for(int i=0; i<scope.length; i++) {
            set.add(Integer.valueOf(scope[i]));
            // Integer는 자체적으로 Comparable을 구현하고 있으므로 따로 비교기준을 입력하지 않아도 됨
        }
        
        System.out.println("TreeSet: "+set);
        System.out.println("50보다 작은 값: "+set.headSet(50));
        // headSet: Returns a view of the portion of this set whose elements are strictly less than toElement.
        System.out.println("50보다 큰 값: "+set.tailSet(Integer.valueOf(50)));
        // from 포함, to 미포함
        // 50 -> new Integer(50) 자동 형변환
        System.out.println("From 40 to 80: "+set.subSet(4080));
    }
}
 
 
 

 

HashMap(Key, Value): 순서X, Key 중복X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.*;
 
public class Ex11_16 {
    public static void main(String[] args) {
        // HashMap: 순서X, key 중복X
        HashMap<Object, Object> map = new HashMap<>();
        map.put("abc""1234"); // put: 추가
        map.put("bcd""2345");
        map.put("bcd""3456"); // 최종 "bcd", "3456" 저장
        
        System.out.println(map.size());
        
        Scanner s = new Scanner(System.in);
        
        for(int i=0; i<3; i++) {
            System.out.println("Enter the ID and PW.");
            System.out.print("ID: ");
            String id = s.nextLine().trim(); // enter 단위로 입력 받음
            
            System.out.print("PW: ");
            String pw = s.nextLine().trim();
            System.out.println();
            
            if(!map.containsKey(id)) {
                System.out.println("There is no Identification.");
                System.out.println();
                continue;
                // 반복문 + continue = 아래 반복문 내용을 더이상 수행하지 않고 반복문 첫 문장으로 올라감
            }
            
            if(!map.get(id).equals(pw)) { // get(Object o): value값 반환
                System.out.println("Incorrect Password.");
                System.out.println();
            } else {
                System.out.println("Logined");
                break// 반복문 중단
            }
        } s.close(); // Resource leak: 's' is never closed
    }
}
 
 
 

 

형변환

Collection type value 값 반환 -> (Set) 형변환 X

객체를 부모로 만들고 리모컨을 자손으로 설정 할 수 X (실행할 수 없는 method가 있을 수도 있기 때문)

Map과 Set

Set<Map.Entry<String, Integer>> set = map.entrySet() // Set<Map.Entry<K,V>> entrySet()

Iterator<Map.Entry<K, V>> it = set.iterator<Map.Entry<K, V>>();

set = map.keySet(); // Set<K> keySet()

Set의 Generics를 <Map.Entry<String, Integer>>로 선언 시, Set<K> keySet()를 사용하지 못하는 문제 발생 -> Generics 선언 X

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.util.*;
 
public class Ex11_17 {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple", Integer.valueOf(95));
        map.put("Apple", Integer.valueOf(100));
        map.put("Banana", Integer.valueOf(40));
        map.put("Car", Integer.valueOf(75));
        map.put("Document", Integer.valueOf(60));
        
        Set set = map.entrySet();
        // Set<Map.Entry<K, V>> entrySet(); -> 차후 Set<K> keySet() 사용 X (형변환X)
        // entrySet(): key, value 참조
        // set.iterator: map에서 쓸 수 없으므로 set으로 형 변환
        Iterator it = set.iterator();
        
        //<Map.Entry<String, Integer>>
        while(it.hasNext()) { // 읽을 요소가 남아있는지 확인
            Map.Entry e = (Map.Entry) it.next(); // 읽은 요소 map type으로 반환
            // Map interface 안에 Entry interface: 
            System.out.println("Name: "+e.getKey()+", Score: "+e.getValue());
        }
 
        set = map.keySet(); // Set type key값 반환
        System.out.println("NameList: "+set);
        
        Collection<Integer> collection = map.values();
        if(collection instanceof Set) {System.out.println("ScoreList: "+collection);}
        // Collection type value 값 반환 -> (Set) 형변환X
        // 객체를 부모로 만들고 리모컨을 자손으로 설정 할 수 X (실행할 수 없는 method가 있을 수도 있기 때문)
        else {System.out.println("Something is Worng.");}
        
        Collection<Integer> values = map.values(); 
        it = values.iterator();
        
        int total = 0;
        
        while(it.hasNext()) {
            Integer i = (Integer) it.next();
            total += i.intValue(); // Integer -> int
            // int i = (int) it.next(); // AutoBoxing
            // total += i;
        }
        
        System.out.println("Total: "+total);
        System.out.println("Average: "+(float)total/set.size());
        System.out.println("Max: "+Collections.max(values));
        System.out.println("Min: "+Collections.min(values));
    }
}
 
 
 

 

조상 class의 가용 method가 적을 때는 자손 class를 활용하여 더 많은 method 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
 
public class Ex11_18 {
    public static void main(String[] args) {
        String[] data = {"A""B""A""D""C""B""A""B""A""D""D""C""D"};
        
        HashMap map = new HashMap();
        
        for(int i=0; i<data.length; i++) {
            if(map.containsKey(data[i])) {
                // map이 data[0](A)값을 갖고 있다면,
                int value = (int) map.get(data[i]);
                // value에 map에서 data[0]인 value를 반환
                map.put(data[i], value+1);
                // map에 data[0](key) value(value)값에 1을 추가
            } else {map.put(data[i], 1);}
            // map이 data[0]이 없다면 map에 key-data[0] value-1추가
        }
        
        Iterator it = map.entrySet().iterator();
        // Iterator: collection에 저장된 Element들을 읽어오는 방법을 표준화
        // map.entrySet() : Set type
        
        while(it.hasNext()) { // iteration이 읽어올 다음 요소가 있을 경우, true를 반환
            Map.Entry entry = (Map.Entry) it.next(); // iteration의 다음 element를 읽어옴
            int value = (int) entry.getValue(); // map에는 가용 method가 적으므로 map.entry 이용
            System.out.println(entry.getKey()+": "
                            +printBar('*', value)+" "+value);
        }
    }
    
    public static String printBar(char ch, int value) {
        char[] bar = new char[value];
        // bar에 길이가 value(4)인 char type 배열 생성
        
        for(int i=0; i<bar.length; i++) {
            bar[i] = ch;
        } return new String(bar); // char[] -> String
    }
}
 
 
 

 

list의 다양한 method()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.*;
import static java.util.Collections.*;
 
public class Ex11_19 {
    public static void main(String[] args) {
        List list = new ArrayList();
        System.out.println("list "+list);
        
        addAll(list, 1,2,3,4,5);
        // 원칙:Collections.addAll -> static을 import할 경우, class이름 생략 가능
        System.out.println("addAll "+list);
        
        rotate(list, 1);
        // 맨뒤 -> 맨 앞으로 이동하면서 회전
        System.out.println("rotate "+list);
        
        swap(list, 0,2);
        System.out.println("swap "+list);
        
        shuffle(list);
        System.out.println("shuffle "+list);
        
        sort(list);
        System.out.println("sort "+list);
        
        sort(list, reverseOrder());
        // 역순 정렬(reverse(list); 와 동일
        System.out.println("reverseOrderSort "+list);
        
        int idx = binarySearch(list, 3);
        System.out.println("IDX of 3 is "+idx);
        
        System.out.println("Max: "+max(list));
        System.out.println("Min: "+min(list));
        System.out.println("Min: "+max(list,reverseOrder()));
        
        fill(list, 9);
        System.out.println("fill "+list);
        
        List newList = nCopies(list.size(),2);
        // list와 같은 크기의 list를 생성하고, 2로 채움, 결과는 변경 불가
        System.out.println("newList "+newList);
        
        System.out.println("disjoint: "+disjoint(list, newList));
        // 공통요소가 1개도 없으면 true
        
        copy(list, newList); // newList에 있는 것을 list에 복사
        System.out.println("newList "+newList);
        System.out.println("list "+list);
        
        replaceAll(list, 21);
        System.out.println("replaceAll "+list);
        
        Enumeration e = enumeration(list);
        // iterator와 동일
        ArrayList list2 = list(e);
        System.out.println("ArrayList "+list2);        
    }
}
 
 
 

 

 

 

소스 코드

🔗 HJ0216/java-practice

 

참고 자료

 

Java - 11.1 TreeSet

- 이진 검색 트리(binary search tree)라는 자료구조의 형태로 데이터를 저장하는 컬렉션 클래스이다. - 정...

blog.naver.com

 

자바 맵 – keySet() vs. entrySet() vs. values() 메서드

1. 개요 이 사용방법(예제)에서는 Java에서 Map 인터페이스 의 세 가지 메서드인 keySet() , entrySet() 및 values() 에 대해 설명합니다. 이러한 메서드는 각각 키 집합, 키-값 매핑 집합 및 값 모음을 검색

recordsoflife.tistory.com