2020년 10월 27일
업데이트:
List
LinkedList
List의 후손으로, 인접 참조를 링크해 체인처럼 관리한다. 특정 인덱스에서 객체를 제거하거나 추가하게 되면 바로 앞/뒤 링크만 변경하면 되기 때문에 객체 삭제와 삽입이 빈번
하게 일어나는 곳에서는 ArrayList보다 성능이 좋다.
List<E> list = new LinkedList<E>();
Comparable, Comparator
Set
저장 순서가 유지되지 않고, 객체와 null을 중복해서 저장할 수 없다. Set 컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있다.
HashSet
Set에 객체를 저장할 때 hash 함수를 사용하여 처리 속도가 빠르다. 동일 객체 뿐 아니라 동등 객체도 중복하여 저장하지 않는다.
Set<E> set = new HashSet<E>();
LinkedHashSet
HashSet과 거의 동일하지만 Set에 추가되는 순서를 유지한다는 점이 다르다.
Set 실습코드
// Student.java
public class Student implements Comparable<Student>{
//Comparable : 객체의 기본 정렬 기준을 구현하는데 사용하는 인터페이스
private String name;
private int age;
private int javaScore;
public Student() {}
public Student(String name, int age, int javaScore) {
super();
this.name = name;
this.age = age;
this.javaScore = javaScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getJavaScore() {
return javaScore;
}
public void setJavaScore(int javaScore) {
this.javaScore = javaScore;
}
@Override
public String toString() {
return "Studnet [name=" + name + ", age=" + age + ", javaScore=" + javaScore + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + javaScore;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (javaScore != other.javaScore)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int compareTo(Student o) {
// 기본 정렬 기준
// 이름 오름차순으로 정렬
// 반환 값 음수, 0 현재 순서 유지, 양수일 때 바꿈
return this.name.compareTo(o.name);
}
}
package com.kh.collection.set.model.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import javax.rmi.CORBA.Stub;
import com.kh.collection.set.model.vo.Student;
import com.kh.collection.set.model.vo.Student;
public class SetService {
// Set(집합)
// - 데이터의 순서가 존재하지 않음
// - 중복 값을 허용하지 않음 (Null도 한 번만 저장할 수 있음)
public void example1() {
// HashSet
// - 저장되는 객체를 hashCode()를 이용하여 동일 여부를 판단
// --> 동일한 객체가 저장될 경우 중복 제거 진행
Set<String> set = new HashSet<String>();
set.add("안녕하세요");
set.add("안녕");
set.add("반갑습니다");
set.add("공부하세요!");
// 순서 유지 X
System.out.println(set.toString());
// 중복 데이터 X -> 중복 제거
set.add("안녕");
set.add(null);
set.add(null);
set.add(null);
System.out.println(set.toString());
}
public void example2() {
// HashSet, Student 사용
// Student로 타입이 제한된 set 객체를 참조하는 참조변수 set
//Set<Studnet> set = new HashSet<>(); // 오른쪽 Student 생략 가능 --> 타입 추론
Set<Student> set = new LinkedHashSet<Student>();
//LinkedHashSet : 순서를 유지한다.
// 참조변수에 선언된 제네릭을 통해 생성되는 객체의 제네릭을 추론함
set.add(new Student("유현재", 27, 100));
set.add(new Student("강수정", 27, 200));
set.add(new Student("이한솔", 27, 300));
// 중복 삽입
set.add(new Student("유현재", 27, 100));
// 중복 제거를 위해서는 Student에 equals(), hashcode()가 오버라이딩 되어있어야 함
System.out.println(set);
/* hashCode
* - 객체에 대한 서명 또는 checksum(중복 검사)
* -> 객체를 서로 구분하는 용도의 정수
*
*/
// size()
System.out.println("set 크기 : " + set.size());
// remove(Student std)
// System.out.println("삭제 성공 : " + set.remove(new Studnet("이한솔", 27, 300)));
// System.out.println(set);
// set은 순서가 없기 때문에 원하는 데이터만을 꺼내보는 것이 불가능함
// -> 내부에 있는 모든 데이터를 무작위로 다 꺼내는 것은 가능함
// 1. Set -> List로 변환
List<Student> list = new ArrayList<Student>(set);
// collection은 List와 Set의 공통점을 추출해서 만든 인터페이스
// collection Framework -> List, Set, Map이 포함됨
System.out.println("Set - List로 변환");
for(int i = 0; i < set.size(); i++) {
System.out.println(list.get(i));
}
// 2. Iterator 반복자를 이용한 출력
// 단점 : Iterator는 한 방향으로만 접근 가능함(단방향)
// -> ListIterator(양방향)
System.out.println("=========================================================");
Iterator<Student> it = set.iterator();
while(it.hasNext()) {
// hasNext() : 다음 반복 접근할 객체가 있을 경우 true / 없으면 false 반환
System.out.println(it.next());
// next() : 다음 객체를 얻어옴
}
// 3. 향상된 for문
// 배열 또는 컬렉션 요소에 반복 접근하는 용도
System.out.println("향상된 for문");
for(Student std : set) {
System.out.println(std);
}
}
public void example3() {
//TreeSet
// - 검색 기능이 강화된 Set으로
// 계층 구조를 활용한 이진트리 자료구조 형태의 Set
// - 기본적인 Set의 특징 (순서 X, 중복 X) + 정렬
Set<Integer> treeSet = new TreeSet<Integer>();
treeSet.add(5);
treeSet.add(15);
treeSet.add(7);
treeSet.add(3);
treeSet.add(9);
treeSet.add(8);
System.out.println(treeSet);
}
public void example4() {
// 로또 번호 생성기
Set<Integer> lotto = new TreeSet<Integer>();
while(lotto.size() < 7) {
int random = (int)(Math.random() * 45 + 1);
lotto.add(random);
}
System.out.println(lotto);
}
public void example5() {
Set<Student> set = new TreeSet<Student>();
set.add(new Student("홍길동", 29, 80));
set.add(new Student("유관순", 28, 90));
set.add(new Student("이이", 25, 85));
set.add(new Student("도레미", 26, 100));
set.add(new Student("세종", 32, 95));
for(Student std : set) {
System.out.println(std);
}
}
public void example6() {
// 숫자 7개를 입력받아
// 생성된 로또 번호와 몇 개가 일치하는지 출력
List<Integer> lotto = new ArrayList<Integer>();
Set<Integer> comLotto = new TreeSet<Integer>();
Scanner sc = new Scanner(System.in);
int count = 0;
System.out.print("숫자 7개 입력 : ");
while(comLotto.size() < 7) {
if(lotto.isEmpty()) {
for(int i = 0; i < 7; i++) {
int num = sc.nextInt();
lotto.add(num);
}
}
int random = (int)(Math.random() *45 +1);
comLotto.add(random);
List<Integer> list = new ArrayList<Integer>(comLotto);
}
System.out.println("생성된 로또 번호 : " + comLotto);
System.out.print("일치하는 번호 : ");
for(int i : comLotto) {
for(int j = 0; j < lotto.size(); j++) {
if(i == lotto.get(j)) {
System.out.print(i + " ");
count++;
}
}
}
System.out.println("\ncount : " + count);
}
}
}
Map
키(Key)와 값(Valuse)으로 구성되어 있으며, 키와 값은 모두 객체이다. 키는 중복 저장을 허용하지 않고(Set방식), 값은 중복 저장 가능(list방식) 키가 중복된 경우, 기존에 있는 키에 해당하는 값을 덮어씌움
HashMap
키 객체는 hashCode()와 equals()를 재정의해 동등 객체가 될 조건을 정해야한다. 때문에 키 타입은 hashCode와 equals() 메소드가 재정의 되어 있는 String
타입을 주로 사용한다.
Map 실습 코드
// Member.java
package com.kh.collection.map.model.vo;
public class Member {
private String id;
private String password;
private String name;
private String birthDay;
private String phone;
public Member() {
// TODO Auto-generated constructor stub
}
public Member(String id, String password, String name, String birthDay, String phone) {
super();
this.id = id;
this.password = password;
this.name = name;
this.birthDay = birthDay;
this.phone = phone;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBirthDay() {
return birthDay;
}
public void setBirthDay(String birthDay) {
this.birthDay = birthDay;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Member [id=" + id + ", password=" + password + ", name=" + name + ", birthDay=" + birthDay + ", phone="
+ phone + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((birthDay == null) ? 0 : birthDay.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((password == null) ? 0 : password.hashCode());
result = prime * result + ((phone == null) ? 0 : phone.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Member other = (Member) obj;
if (birthDay == null) {
if (other.birthDay != null)
return false;
} else if (!birthDay.equals(other.birthDay))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (phone == null) {
if (other.phone != null)
return false;
} else if (!phone.equals(other.phone))
return false;
return true;
}
}
// SetService.java
package com.kh.collection.set.model.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
import javax.rmi.CORBA.Stub;
import com.kh.collection.set.model.vo.Student;
import com.kh.collection.set.model.vo.Student;
public class SetService {
// Set(집합)
// - 데이터의 순서가 존재하지 않음
// - 중복 값을 허용하지 않음 (Null도 한 번만 저장할 수 있음)
public void example1() {
// HashSet
// - 저장되는 객체를 hashCode()를 이용하여 동일 여부를 판단
// --> 동일한 객체가 저장될 경우 중복 제거 진행
Set<String> set = new HashSet<String>();
set.add("안녕하세요");
set.add("안녕");
set.add("반갑습니다");
set.add("공부하세요!");
// 순서 유지 X
System.out.println(set.toString());
// 중복 데이터 X -> 중복 제거
set.add("안녕");
set.add(null);
set.add(null);
set.add(null);
System.out.println(set.toString());
}
public void example2() {
// HashSet, Student 사용
// Student로 타입이 제한된 set 객체를 참조하는 참조변수 set
//Set<Studnet> set = new HashSet<>(); // 오른쪽 Student 생략 가능 --> 타입 추론
Set<Student> set = new LinkedHashSet<Student>();
//LinkedHashSet : 순서를 유지한다.
// 참조변수에 선언된 제네릭을 통해 생성되는 객체의 제네릭을 추론함
set.add(new Student("유도리", 27, 100));
set.add(new Student("강해", 27, 200));
set.add(new Student("이끼", 27, 300));
// 중복 삽입
set.add(new Student("유도리", 27, 100));
// 중복 제거를 위해서는 Student에 equals(), hashcode()가 오버라이딩 되어있어야 함
System.out.println(set);
/* hashCode
* - 객체에 대한 서명 또는 checksum(중복 검사)
* -> 객체를 서로 구분하는 용도의 정수
*
*/
// size()
System.out.println("set 크기 : " + set.size());
// remove(Student std)
// System.out.println("삭제 성공 : " + set.remove(new Studnet("이끼", 27, 300)));
// System.out.println(set);
// set은 순서가 없기 때문에 원하는 데이터만을 꺼내보는 것이 불가능함
// -> 내부에 있는 모든 데이터를 무작위로 다 꺼내는 것은 가능함
// 1. Set -> List로 변환
List<Student> list = new ArrayList<Student>(set);
// collection은 List와 Set의 공통점을 추출해서 만든 인터페이스
// collection Framework -> List, Set, Map이 포함됨
System.out.println("Set - List로 변환");
for(int i = 0; i < set.size(); i++) {
System.out.println(list.get(i));
}
// 2. Iterator 반복자를 이용한 출력
// 단점 : Iterator는 한 방향으로만 접근 가능함(단방향)
// -> ListIterator(양방향)
System.out.println("=========================================================");
Iterator<Student> it = set.iterator();
while(it.hasNext()) {
// hasNext() : 다음 반복 접근할 객체가 있을 경우 true / 없으면 false 반환
System.out.println(it.next());
// next() : 다음 객체를 얻어옴
}
// 3. 향상된 for문
// 배열 또는 컬렉션 요소에 반복 접근하는 용도
System.out.println("향상된 for문");
for(Student std : set) {
System.out.println(std);
}
}
public void example3() {
//TreeSet
// - 검색 기능이 강화된 Set으로
// 계층 구조를 활용한 이진트리 자료구조 형태의 Set
// - 기본적인 Set의 특징 (순서 X, 중복 X) + 정렬
Set<Integer> treeSet = new TreeSet<Integer>();
treeSet.add(5);
treeSet.add(15);
treeSet.add(7);
treeSet.add(3);
treeSet.add(9);
treeSet.add(8);
System.out.println(treeSet);
}
public void example4() {
// 로또 번호 생성기
Set<Integer> lotto = new TreeSet<Integer>();
while(lotto.size() < 7) {
int random = (int)(Math.random() * 45 + 1);
lotto.add(random);
}
System.out.println(lotto);
}
public void example5() {
Set<Student> set = new TreeSet<Student>();
set.add(new Student("이준호", 29, 80));
set.add(new Student("김영주", 28, 90));
set.add(new Student("김정화", 25, 85));
set.add(new Student("고보석", 26, 100));
set.add(new Student("박희도", 32, 95));
for(Student std : set) {
System.out.println(std);
}
}
public void example6() {
// 숫자 7개를 입력받아
// 생성된 로또 번호와 몇 개가 일치하는지 출력
List<Integer> lotto = new ArrayList<Integer>();
Set<Integer> comLotto = new TreeSet<Integer>();
Scanner sc = new Scanner(System.in);
int count = 0;
System.out.print("숫자 7개 입력 : ");
while(comLotto.size() < 7) {
if(lotto.isEmpty()) {
for(int i = 0; i < 7; i++) {
int num = sc.nextInt();
lotto.add(num);
}
}
int random = (int)(Math.random() *45 +1);
comLotto.add(random);
List<Integer> list = new ArrayList<Integer>(comLotto);
}
System.out.println("생성된 로또 번호 : " + comLotto);
System.out.print("일치하는 번호 : ");
for(int i : comLotto) {
for(int j = 0; j < lotto.size(); j++) {
if(i == lotto.get(j)) {
System.out.print(i + " ");
count++;
}
}
}
System.out.println("\ncount : " + count);
}
public void example6_1() {
Set<Integer> inputSet = new HashSet<Integer>(); // 입력용 Set
Set<Integer> lotto = new TreeSet<Integer>(); // 로또용 set
List<Integer> sameNum = new ArrayList<>();
// 1. 번호 입력
System.out.print("숫자 7개 입력 : ");
Scanner sc = new Scanner(System.in);
while(inputSet.size() < 7) {
inputSet.add(sc.nextInt());
}
// 2. 로또 생성 + 일치하는 카운트 + 일치 번호 저장
int count = 0;
while(lotto.size() < 7) {
int random = (int)(Math.random() * 45 + 1);
if(lotto.add(random)) { // Set에 정상 추가될 경우 true
for(int input : inputSet) {
if(input == random) {
sameNum.add(input);
count++;
break;
}
}
}
}
}
}
댓글남기기