본문 바로가기

웹개발 수업/JAVA

[Day +24]Collection / List, Comparable, Comparator, Set, HashSet, ListIterator, TreeSet

210726 월

 

Collection 

1. List

1) Comparable vs Comparator

 

 

package com.kh.chap01_list.part03_sort.controller;

import java.util.ArrayList;
import java.util.Collections;

import com.kh.chap01_list.part03_sort.model.comparator.AscName;
import com.kh.chap01_list.part03_sort.model.comparator.AscScore;
import com.kh.chap01_list.part03_sort.model.comparator.DescName;
import com.kh.chap01_list.part03_sort.model.comparator.DescScore;
import com.kh.chap01_list.part03_sort.model.vo.Student;

public class StudentController {
	
	public void testSort() {
	ArrayList<Student> stList = new ArrayList<>();
	stList.add(new Student("박영희", 80));
	stList.add(new Student("김영희", 60));
	stList.add(new Student("한영희", 100));
	
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));
	}
	//java.util.Comparator의 compare메소드 사용
	//새로운 클래스를 생성하여 Comparator 상속 받고 compare 메소드 오버라이딩하여
	//정렬 기준 재 정의 => 여러개의 정렬 기준 설정 가능
	System.out.println("=====Comparator=====");
	System.out.println("=====점수 오름차순 정렬=====");
	
	//AscScore클래스 만들기
	Collections.sort(stList, new AscScore());
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));
	}
	System.out.println("=====점수 내림차순 정렬=====");
	//DescScore 클래스 만들기
	Collections.sort(stList, new DescScore());
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));
	}
	
	System.out.println("=====이름 오름차순 정렬=====");
	//AscName클래스 만들기
	Collections.sort(stList, new AscName());
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));
//		=====전체 리스트 출력=====
//		Student [name=박영희, score=80]
//		Student [name=김영희, score=60]
//		Student [name=한영희, score=100]
//		=====Comparator=====
//		=====점수 오름차순 정렬=====
//		=====전체 리스트 출력=====
//		Student [name=김영희, score=60]
//		Student [name=박영희, score=80]
//		Student [name=한영희, score=100]
//		=====점수 내림차순 정렬=====
//		=====전체 리스트 출력=====
//		Student [name=한영희, score=100]
//		Student [name=박영희, score=80]
//		Student [name=김영희, score=60]
//		=====이름 오름차순 정렬=====
//		=====전체 리스트 출력=====
//		Student [name=김영희, score=60]
//		Student [name=박영희, score=80]
//		Student [name=한영희, score=100]
}
	System.out.println("=====이름 내림차순 정렬=====");
	//DescName 클래스 만들기
	Collections.sort(stList, new DescName());
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));

//		=====이름 내림차순 정렬=====
//		=====전체 리스트 출력=====
//		Student [name=한영희, score=100]
//		Student [name=박영희, score=80]
//		Student [name=김영희, score=60]
	}

	//java.lang.Comparable의 compareTo 메소드
	//정렬하고자 하는 객체에 Comparable 상속 받아 compareTo 메소드 오버라딩
	//해서 정렬 기준 재정의
	System.out.println("=====Comparable=====");
	System.out.println("=====점수 오름차순=====");
	Collections.sort(stList);
	System.out.println("=====전체 리스트 출력=====");
	for(int i = 0 ; i < stList.size(); i++) {
		System.out.println(stList.get(i));}
	
//	=====Comparable=====
//			=====점수 오름차순=====
//			=====전체 리스트 출력=====
//			Student [name=김영희, score=60]
//			Student [name=박영희, score=80]
//			Student [name=한영희, score=100]
	

}
}

1-1> AscName

package com.kh.chap01_list.part03_sort.model.comparator;

import java.util.Comparator;

import com.kh.chap01_list.part03_sort.model.vo.Student;

public class AscName implements Comparator<Student>{

	@Override
	public int compare(Student o1, Student o2) {
		//String 클래스에서 제공하는 compartTo 메소드 사용
		//문자열 오름차순(사전 순)으로 앞이 크면 1, 같으면 0, 뒤가 크면 -1 반환

		return o1.getName().compareTo(o2.getName()) ;
	}

}

1-2> DescName

package com.kh.chap01_list.part03_sort.model.comparator;

import java.util.Comparator;

import com.kh.chap01_list.part03_sort.model.vo.Student;

//이름 내림차순
public class DescName implements Comparator<Student>{

	@Override
	public int compare(Student o1, Student o2) {
		return o2.getName().compareTo(o1.getName());
	}

}

2-1> AscScore

package com.kh.chap01_list.part03_sort.model.comparator;

import java.util.Comparator;

import com.kh.chap01_list.part03_sort.model.vo.Student;

//점수별 오름차순
public class AscScore implements Comparator<Student> {

	@Override
	public int compare(Student o1, Student o2) {
		return o1.getScore() - o2.getScore();
	}

//	@Override
//	public int compare(Object o1, Object o2) {
//		//o1(왼쪽) vs o2(오른쪽)
//		int standard = ((Student)o1).getScore();
//		int object = ((Student)o2).getScore();
//		
//		
//		if(standard > object) {
//			//점수 오름차순 기준으로 값 변경이 필요하므로 양수 1을 리턴한다
//			return 1;
//		}else if(standard == object) {
//			//두 값이 같은 경우
//			return 0;
//		}else {
//			//점수 오름차순 기준으로 값 변경 필요하지 앟으므로 음수 -1리턴
// 			return -1;
//		}
//		//return 0;
//		
//		return standard - object;
//	}
	

}

2-2> DescScore

package com.kh.chap01_list.part03_sort.model.comparator;

import java.util.Comparator;

import com.kh.chap01_list.part03_sort.model.vo.Student;

//점수 내림차순
public class DescScore implements Comparator<Student> {

	@Override
	public int compare(Student o1, Student o2) {
		
		//오름차순 정렬과 반대된 기준을 전달하도록 처리하면 됨
		//return o2.getScore() - o1.getScore();
		//return -(o1.getScore() - o2.getScore());
		return (o1.getScore() - o2.getScore()) * (-1);
	}

}
package com.kh.chap01_list.part03_sort.model.vo;

public class Student implements Comparable<Student>{

	private String name;
	private int score;
	
	public Student() {}

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

	public String getName() {
		return name;
	}

	public int getScore() {
		return score;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setScore(int score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}

	@Override
	public int compareTo(Student o) {
		//점수 오름차순
		//this vs Student o
		return score - o.getScore();
	}
	
	
}
package com.kh.chap01_list.part03_sort.run;

import com.kh.chap01_list.part03_sort.controller.StudentController;

public class Run {

	public static void main(String[] args) {
		
		StudentController sc = new StudentController();
		sc.testSort();
		
	}

}

 

2. Set

: 저장 순서가 유지되지 않고, 중복 객체도 저장하지 못하게 하는 자료 구조

-null도 중복을 허용하지 않기 때문에 1개의 null만 저장

-구현 클래스로 HashSet, LinkedSet, TreeSet이 있음

 

1) 구현 클래스 종류

(1) HashSet

-Set에 객체를 저장할 때 hash함수를 사용하여 처리 속도가 빠름

-동일 객체 뿐 아니라 동등 객체도 중복하여 저장하지 않음

package com.kh.chap02_set.part01_hashSet.controller;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Set;


import com.kh.chap02_set.part01_hashSet.model.vo.Student;



/*
 * Set계열의 특징 : 저장 순서 유지X, 중복 저장X
 * Set계열의 종류 : HashSet, LinkedHashSet, TreeSet
 */

public class HashSetTest {

	public void doHashSet() {
		
		//Set은 인터페이스이므로 객체 생성 불가
		//Set set = new Set();
		
		//Set의 후손 클래스로 객체 생성(다형성)
		//Set set = new HashSet();
		
		
		System.out.println("======= String 클래스로 테스트 =======");
		HashSet<String> set = new HashSet<>();
		set.add("안녕하세요");
		set.add("우리는 지금");
		set.add("Set 공부중");
		System.out.println(set);
		//=> 저장 순서 유지 되지 않음
		
		
//		======= String 클래스로 테스트 =======
//		  [안녕하세요, Set 공부중, 우리는 지금]

		set.add("안녕하세요");
		System.out.println(set);
		//=> 중복 객체 저장 불가
		
//		======= String 클래스로 테스트 =======
//		[안녕하세요, Set 공부중, 우리는 지금]
//		[안녕하세요, Set 공부중, 우리는 지금]

		System.out.println("=====Student클래스로 테스트=====");
		HashSet<Student> hs = new HashSet<>();
		
		//add,(
		hs.add(new Student("한영희", 100));
		hs.add(new Student("박영희", 60));
		hs.add(new Student("김영희", 80));
		System.out.println(hs);
		//=> 저장 순서 유지하지 않음
		
		hs.add(new Student("한영희", 100));
		System.out.println(hs);
		//필드 값이 동일한 객체를 저장했으나 중복 저장 되는 모습을 확인 가능하다
		//Student에 hashCode 오버라이딩 되어 있지 않아서
		//HashSet에 저장 시 Object의 hashCode가 호출 되었음
		//필드 값 비교가 아닌 주소 값 비교로 저장되어 중복 객체 제거 기능하지 못함
		//Student 클래스에 hashCode&equals 오버라이딩 처리하기
		
//		=====Student클래스로 테스트=====
//		[Student [name=한영희, score=100], Student [name=박영희, score=60], 
//		 			Student [name=김영희, score=80]]
//		[Student [name=한영희, score=100], Student [name=한영희, score=100], 
//		 Student [name=박영희, score=60], Student [name=김영희, score=80]]
		
		
		//오버라이딩 처리 후
//		=====Student클래스로 테스트=====
//		[Student [name=한영희, score=100], 
//		 Student [name=김영희, score=80], Student [name=박영희, score=60]]
//		[Student [name=한영희, score=100], Student [name=김영희, score=80], 
//		 Student [name=박영희, score=60]]
		
		
		System.out.println("=====HashSet 출력 테스트=====");
		//index가 없으므로 get(int index)이용한 일반 for문으로는 접근 불가
		//(1) for each문으로 접근하기
		for(Student st : hs) {
			System.out.println(st);
//		=====HashSet 출력 테스트=====
//		Student [name=한영희, score=100]
//		Student [name=김영희, score=80]
//		Student [name=박영희, score=60]
		}
		
		//(2) Iterator(반복자) 사용
		 Iterator<Student> it = hs.iterator();
		 while(it.hasNext()) {
			 System.out.println(it.next());
			 
//		Student [name=한영희, score=100]
//		Student [name=김영희, score=80]
//		Student [name=박영희, score=60]
		}
		 
	 //ListIterator : list에서만 구현 가능한 양방향 Iterator
	System.out.println("=====ListIterator테스트 =====");
	ArrayList<Student> list = new ArrayList<>();
	//hs의 데이터를 list로 옮기기 위해 addAll 메소드 사용
	list.addAll(hs);
	System.out.println(list);
//	=====ListIterator테스트 =====
//	[Student [name=한영희, score=100], Student 
//	[name=김영희, score=80], Student [name=박영희, score=60]]	
	
	
	ListIterator<Student> lit = list.listIterator();	
	
	
	//순방향
	while(lit.hasNext()) {
		System.out.println(lit.next());
		
	}
	System.out.println("==============================");
	//역방향
	
	while(lit.hasPrevious()){
		System.out.println(lit.previous());
	}
	
//			Student [name=한영희, score=100]
//			Student [name=김영희, score=80]
//			Student [name=박영희, score=60]
//			==============================
//			Student [name=박영희, score=60]
//			Student [name=김영희, score=80]
//			Student [name=한영희, score=100]

	}
}
package com.kh.chap02_set.part01_hashSet.model.vo;

public class Student {

		private String name;
		private int score;
		
		public Student() {}

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

		public String getName() {
			return name;
		}

		public int getScore() {
			return score;
		}

		public void setName(String name) {
			this.name = name;
		}

		public void setScore(int score) {
			this.score = score;
		}

		@Override
		public String toString() {
			return "Student [name=" + name + ", score=" + score + "]";
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			result = prime * result + score;
			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 (name == null) {
				if (other.name != null)
					return false;
			} else if (!name.equals(other.name))
				return false;
			if (score != other.score)
				return false;
			return true;
		}
	
}
package com.kh.chap02_set.part01_hashSet.run;

import com.kh.chap02_set.part01_hashSet.controller.HashSetTest;

public class Run {

	public static void main(String[] args) {
		
		HashSetTest ht = new HashSetTest();
		ht.doHashSet();

	}

}

(2) LinkedHashSet

HashSet과 거의 동일하지만 Set에 추가되는 순서를 유지한다는 점이 다름

 

2) Set계열 주요 메소드

 

*Enumeration, Iterator, ListIterator
컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스

(1) Enumeration

: Iterator의 구버전

 

(2) ListIterator

: Iterator를 상속받아 양방향 특징

package com.kh.chap02_set.part02_treeSet.controller;

import java.util.TreeSet;

import com.kh.chap02_set.part02_treeSet.model.vo.Student;

public class TreeSetTest {

	public void doTreeSet() {
		
		System.out.println("=====Integer 클래스로 테스트=====");
		TreeSet<Integer> set = new TreeSet<Integer>();
		set.add(new Integer(10));
		set.add(new Integer(5));
		set.add(15);
		System.out.println(set);
//		=====Integer 클래스로 테스트=====
//		[5, 10, 15]
		
		//문자열 추가해보기
//		set.add("끝");
//		System.out.println(set);
		//java.lang.ClassCastException: 발생
		//Tree는 정렬 기준을 가지고 값을 저장하므로 같은 타입이 아닌 값이 들어오면 저장 불가능함

		System.out.println("=====Student 클래스로 테스트=====");
		TreeSet<Student> ts = new TreeSet<>();
		ts.add(new Student("김영희", 80));
		ts.add(new Student("한영희", 100));
		ts.add(new Student("박영희", 60));
		System.out.println(ts);
		//java.lang.ClassCastException : Student cannot be cast to java.lang.Comparable 이 오류 발생
		//Tree는 정렬 기준을 가지고 값을 저장하는데 Student 객체에 대한 아무런 정렬
		//기준이 정의되지 않아서 값 추가가 불가능함 => Comparable 구현 필요함
		
			
//		=====Student 클래스로 테스트=====
//		[Student [name=김영희, score=80], 
//		Student [name=박영희, score=60], Student [name=한영희, score=100]]
		
		//이름 오름차순 정렬 기준으로 저장 중일 때 이름이 같은 값은 중복 제거
		ts.add(new Student("한영희", 99));
		//성적(오름차순) 정렬 기준으로 저장 중일 떄 성적이 같은 값은 중복 제거
		ts.add(new Student("우영희", 100));
		System.out.println(ts);
		//[Student [name=박영희, score=60], Student [name=김영희, score=80], 
		//Student [name=한영희, score=99], Student [name=한영희, score=100]]
		//성적 같은 사람 제거됨
		//[Student [name=김영희, score=80], Student [name=박영희, score=60], 
		//Student [name=우영희, score=100], Student [name=한영희, score=100]]
		//=> 우영희만 추가되었다.
	}

}
package com.kh.chap02_set.part02_treeSet.model.vo;

public class Student implements Comparable<Student>{


	private String name;
	private int score;
	
	public Student() {}

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

	public String getName() {
		return name;
	}

	public int getScore() {
		return score;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setScore(int score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + "]";
	}

	@Override
	public int compareTo(Student o) {
		//this vs Student o
		//이름 오름차순 정렬
		//return name.compareTo(o.getName());
		//성적 오름차순 정렬
		return score - o.getScore();
	}
}
package com.kh.chap02_set.part02_treeSet.run;

import com.kh.chap02_set.part02_treeSet.controller.TreeSetTest;

public class Run {

	public static void main(String[] args) {
		TreeSetTest tt = new TreeSetTest();
		tt.doTreeSet();
		
	}

}

(3) LinkedSet

: 저장 순서를 기억합니다.

 

(4) TreeSet

: 검색 기능을 강화시킨 컬렉션으로, 계층 구조를 활용해 이진 트리 자료구조를 구현하여 제공

1>  장점 : 검색 기능의 강화