공부기록/사전학습

Java 사전학습_7

루팽 2022. 11. 19. 13:35

<Java 사전학습_7>

  1. 기본 클래스-Object(31강)
  2. 기본 클래스-String, Wrapper(32강)
  3. 제너릭 프로그래밍(33강)
  4. 컬렉션 프레임워크(34강)
  5. 컬렉션 프레임워크-ArrayList(35강)
  6. 컬렉션 프레임워크-Stack, Queue, HashSet(36강)
  7. 컬렉션 프레임워크-TreeSet, HashMap, TreeMap(37강)

 


 

1. 기본 클래스-Object(31강)

java.lang 패키지
프로그래밍 시 import하지 않아도 자동으로 import 됨
import java.lang.*; 문장이 추가됨
많이 사용하는 기본 클래스들이 속한 패키지
String, Integer, System 등

Object 클래스
모든 클래스의 최상위 클래스
java.lang.Object 클래스
모든 클래스는 Object클래스에서 상속 받음
모든 클래스는 Object클래스의 메서드를 사용할 수 있음
모든 클래스는 Object클래스의 메서드 중 일부는 재정의할 수 있음(final로 선언된 메서드는 재정의 불가)
컴파일러가 extends Object를 추가함

Object 클래스 메서드

메서드 설명
String toString() 객체를 문자열로 표현하여 반환합니다. 재정의하여 객체에 대한 설명이나 특정 멤버 변수값을 반환합니다.
boolean equals(Object obj) 두 인스턴스가 동일한지 여부를 반환합니다. 재정의하여 논리적으로 동일한 인스턴스임을 정의할 수 있습니다.
int hashCode() 객체의 해시 코드 값을 반환합니다.
Object clone() 객체를 복제하여 동일한 멤버 변수값을 가진 새로운 인스턴스를 생성합니다.
Class getClass() 객체의 Class클래스를 반환합니다.
void finalize() 인스턴스가 힙 메모리에서 제거될 때 가비지 컬렉터(GC)에 의해 호출되는 메서드입니다. 네트워크 연결 해제, 열려있는 파일 스트림 해제 등을 구현합니다.
void wait() 멀티스레드 프로그램에서 사용하는 메서드입니다. 스레드를 ‘기다리는 상태(non runnable)’로 만듭니다.
void notify() wait() 메서드에 의해 기다리고 있는 스레드를 실행 가능한 상태(runnable)로 가져옵니다.


toString() 메서드
Object클래스의 메서드
객체의 정보를 String으로 바꾸어서 사용할 때 많이 쓰임
String이나 Integer클래스에서는 이미 재정의 되어있음
String은 문자열 반환
Integer는 정수 값 반환

package object;
class Book{
	String title;
	String author;
	
	Book(String title, String author) {
		this.title = title;
		this.author = author;
	}

	@Override
	public String toString() {
		return title + ", " + author;
	}
}

public class ToStringEx {
	public static void main(String[] args) {
		Book book = new Book("나무타기개론", "루팽구");
		System.out.println(book);
		
		String str = new String("test");
		System.out.println(str);
	}
}


equals() 메서드
두 인스턴스의 주소 값을 비교하여 true/false를 반환
재정의하여 두 인스턴스가 논리적으로 동일함의 여부를 반환

package object;

class Student{
	int studentID;
	String studentName;
	
	Student(int studentID, String studentName) {
		this.studentID = studentID;
		this.studentName = studentName;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student) {
			Student std = (Student)obj;
			if(studentID == std.studentID)
				return true;
			else
				return false;
		}
		return false;
	}
	
}

public class EqulasTest {
	public static void main(String[] args) {
		String str1 = new String("test");
		String str2 = new String("test");
		
		System.out.println(str1 == str2); //false, 주소다름
		System.out.println(str1.equals(str2)); //true, 문자열같음
		
		Student std1 = new Student(0001, "Luka");
		Student std2 = new Student(0001, "Luka");
		
		System.out.println(std1 == std2); //false
		System.out.println(std1.equals(std2)); //true
	}
}


hashCode() 메서드
hase-정보를 저장, 검색하기 위해 사용하는 자료구조
자료의 특정 값(키 캆)에 대해 저장 위치를 반환해주는 해시 함수를 사용함

index = hash(key) //저장위치 = 해시함수(객체정보)

해시함수는 어떤 정보인가에 따라 다르게 구현됨
hashCode() 메서드는 인스턴스의 저장 주소를 반환함
힙 메모리에 인스턴스가 저장되는 방식이 hash
hashCode()의 반환 값은 자바 가상 머신이 저장한 인스턴스의 주소 값을 10진수로 나타냄
서로 다른 메모리의 두 인스턴스가 같다면 재정의된 equlas() 메서드의 값이 ture, 동일한 hashCode() 반환 값을 가져야 함
논리적으로 동일함을 위해 equlas() 메서드를 재정의했다면 hashCode() 메서드로 재정의하여 동일한 값이 반환되도록 함

String클래스
동일한 문자열 인스턴스에 대해 동일한 정수가 반환

Integer클래스
동일한 정수 값의 인스턴스에 대해 같은 정수 값이 반환됨

clone() 메서드
객체의 원본을 복제하는 데 사용
원본을 유지해놓고 복사본을 사용할 때
기본 틀(prototype)을 두고 복잡한 생성과정을 반복하지 않고 복제
clone() 메서드를 사용하면 객체의 정보(멤버 변수 값)가 같은 인스턴스가 또 생성되는 것이므로 객체 지향 프로그램의 정보은닉, 객체 보호의 관점에서 위배될 수 있음
객체의 clone() 메서드 사용을 허용한다는 의미로 cloneable 인터페이스를 명시해줌

Class Circle implements Cloneable {
//객체를 복제해도 된다는 의미로 Cloneable인터페이스를 함께 선언
	Point point;
	int radius;

 

package object;
class Point {
	int x;
	int y;
	
	Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	public String toSrting() {
		return "x=" + x + ", " + "y=" + y;
	}
}

class Circle implements Cloneable{
	Point point;
	private int radius;
	
	public Circle(int x, int y, int radius) {
		point = new Point(x, y);
		this.radius = radius;
	}
	
	public String toString() {
		return "원점은 " + this.point + "이고, 반지름은 " + radius + "입니다.";
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}	
}

public class ObjectCloneTest {
	public static void main(String[] args) throws CloneNotSupportedException {
		Circle circle = new Circle(10, 20, 5);
		Circle cloneCircle = (Circle)circle.clone();
		
		System.out.println(System.identityHashCode(circle)); //617901222
		System.out.println(System.identityHashCode(cloneCircle));//1159190947
		
		System.out.println(circle);
		System.out.println(cloneCircle);
		//원점은 object.Point@372f7a8d이고, 반지름은 5입니다.
	}
}

 

2. 기본 클래스-String, Wrapper(32강)

String 클래스
String을 선언하는 두 가지 방법

String str1 = new String("abc") //생성자의 매개변수로 문자열 생성
String str2 = "test"; //문자열 상수를 가리키는 방식

힙 메모리에 인스턴스로 생성되는 경우와 상수 풀(constant pool)에 있는 주소를 참조하는 방법
상수 풀의 문자열을 참조하면 모든 문자열이 같은 주소를 가리킴

package string;
public class StringTest {
	public static void main(String[] args) {
		String str1 = new String("abc");
		String str2 = new String("abc");
		
		System.out.println(str1 == str2); //false
		
		String str3 = "abc";
		String str4 = "abc";
		
		System.out.println(str3 == str4); //true
	}
}


String클래스로 문자열 연결
한번 생성된 String값(문자열)은 불변(immutable)
두 개의 문자열을 연결하면 새로운 인스턴스가 생성됨
문자열 연결을 계속하면 메모리에 garbage가 많이 생길 수 있음

package string;
public class StringTest {
	public static void main(String[] args) {
		String str1 = new String("java");
		String str2 = new String("android");
		
		System.out.println(System.identityHashCode(str1)); //2055281021
		
		str1 = str1.concat(str2);
		
		System.out.println(System.identityHashCode(str1)); //1554547125
		System.out.println(str1); //javaandroid
	}
}


StringBuilder, StringBuffer 사용하기
내부적으로 가변적인 char [] 배열을 가지고 있는 클래스
문자열을 여러 번 연결하거나 변경할 때 사용하면 유용
매번 새로 생성하지 않고 기존 배열을 변경하므로 garbage가 생기지 않음
StringBuffer는 멀티 스레드 프로그래밍에서 동기화(synchronization)를 보장
단일 스레드 프로그램에서는 StringBuilder를 사용하기를 권장
toString() 메서드로 String반환

package string;
public class StringBuilderTest {
	public static void main(String[] args) {
		String str1 = new String("java");
		
		System.out.println(System.identityHashCode(str1)); //2055281021
		
		StringBuilder buffer = new StringBuilder(str1);
		
		System.out.println(System.identityHashCode(buffer)); //1554547125
		
		buffer.append(" and");
		buffer.append(" android");
		
		System.out.println(System.identityHashCode(buffer)); //1554547125
		
		String str2 = buffer.toString();
		System.out.println(str2); //java and android
	}
}


Wrapper클래스
기본 자료형(primitive data type)에 대한 클래스

기본형 Wrapper클래스
boolean Boolean
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double


오토 박싱(autoboxing)과 언박싱(unboxing)
Integer는 객체이고 int는 4바이트 기본 자료형
두 개의 자료를 같이 연산할 때 자동으로 변환이 일어남

Class 클래스
자바의 모든 클래스와 인터페이스는 컨파일 후 class파일로 생성
class파일에는 객체의 정보(멤버 변수, 메서드, 생성자 등)가 포함되어있음
Class클래스는 컴파일된 class파일에서 객체의 정보를 가져올 수 있음

Class클래스 가져오기
Object클래스의 getClass() 메서드 사용하기

String s = new String();
Class c = s.getClass(); // getClass()메서드의 반환형은 Class


클래스 파일 이름을 Class 변수에 직접 대입하기

Class c = String.Class;


Class.forName(”클래스 이름”)메서드 사용하기

Class c = Class.forName("java.lang.String");

 

package classex;
public class ClassTest {
	public static void main(String[] args) throws ClassNotFoundException {
		Person person = new Person();
		
		Class pClass1 = person.getClass();
		System.out.println(pClass1.getName()); //classex.Person
		
		Class pClass2 = Person.class;
		System.out.println(pClass2.getName()); //classex.Person
		
		Class pClass3 = Class.forName("classex.Person");
		System.out.println(pClass3.getName()); //classex.Person
	}
}


Class클래스로 정보 가져오기
reflection 프로그래밍-Class클래스를 이용하여 클래스의 정보(생성자, 멤버 변수, 메서드)를 가져오고 이를 활용하여 인스턴스를 생성하고 메서드를 호출하는 등의 프로그래밍 방식
로컬 메모리에 객체가 없어서 객체의 데이터 타입을 직접 알 수 없는 경우(원격에 객체가 있는 경우 등) 객체 정보만을 이용하여 프로그래밍에 활용할 수 있음
Constructor, Method, Filed 등 java.lang.raflect 패키지에 있는 클래스들을 활용하여 프로그래밍
일반적으로 자료형을 알 수 있는 경우에는 사용하지 않음

Class.forName() 메서드로 동적 로딩하기
동적 로딩-컴파일 시에 데이터 타입이 모두 binding 되어 자료형이 로딩되는 것(static loading)이 아니라 실행 중에 데이터 타입을 알고 binding 되는 방식
프로그래밍하며 어떤 클래스를 사용할지 모를 때 변수로 처리하고, 실행될 때 해당 변수에 대입된 값의 클래스가 실행될 수 있도록 Class클래스에서 제공하는 static메서드
실행 시에 로딩되므로 경우에 따라 다른 클래스가 사용될 수 있어 유용함
컴파일 타임에 체크할 수 없으므로 해당 문자열에 대한 클래스가 없는 경우 예외(ClassNotFoundException)가 발생할 수 있음

package classex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class StringTest {
	public static void main(String[] args) throws ClassNotFoundException {
		Class strClass = Class.forName("java.lang.String");
		
		Constructor[] cons = strClass.getConstructors();
		
		for(Constructor c : cons) {
			System.out.println(c);
		}
		
		Field[] fields = strClass.getFields();
		
		for(Field f : fields) {
			System.out.println(f);
		}
		
		Method[] methods = strClass.getMethods();
		
		for(Method m : methods) {
			System.out.println(m);
		}
	}
}

 

3. 제너릭 프로그래밍(33강)

제네릭(Generic) 프로그래밍
변수의 선어이나 메서드의 매개변수를 하나의 참조 자료형이 아닌 여러 자료형으로 변환될 수 있도록 프로그래밍하는 방식
실제 사용되는 참조 자료형으로의 변환은 컴파일러가 검증하므로 안정적인 프로그래밍 방식
컬렉션 프레임워크에서 많이 사용되고 있음

제네릭 클래스 정의하기
여러 참조 자료형으로 대체될 수 있는 부분을 하나의 문자로 표현
이 문자를 자료형 매개 변수라고 함

자료형 매개 변수 T
type의 의미로 T를 많이 사용
<T>에서 <>는 다이아몬드 연산자
static키워드는 T에 사용할 수 없음
다이아몬드 연산자 내부에서 자료형은 생략 가능

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

 

package generics;
public class ThreeDPrinter<T extends Material> { //Material을 상속받은 클래스만 사용가능
	private T material;

	public T getMaterial() {
		return material;
	}

	public void setMaterial(T material) {
		this.material = material;
	}
	
	@Override
	public String toString() {
		return material.toString();
	}
	
	public void printing() {
		material.doPrinting();
	}
}

 

package generics;
public abstract class Material {
	public abstract void doPrinting();
}

 

package generics;
public class Plastic extends Material{
	public String toString() {
		return "재료는 Plastic 입니다.";
	}

	@Override
	public void doPrinting() {
		System.out.println("Plastic 재료로 출력합니다.");
	}
}

 

package generics;
public class Powder extends Material{
	public String toString() {
		return "재료는 Powder 입니다.";
	}

	@Override
	public void doPrinting() {
		System.out.println("Powder 재료로 출력합니다.");
	}
}

 

package generics;
public class ThreeDPrinterTest {
	public static void main(String[] args) {
		ThreeDPrinter<Powder> printer1 = new ThreeDPrinter<Powder>();
		printer1.setMaterial(new Powder());
		Powder powder = printer1.getMaterial();
		System.out.println(printer1); //재료는 Powder 입니다.
		
		ThreeDPrinter<Plastic> printer2 = new ThreeDPrinter<Plastic>();
		printer2.setMaterial(new Plastic());
		Plastic plastic = printer2.getMaterial();
		System.out.println(printer2); //재료는 Plastic 입니다.
		
		printer1.printing(); //Powder 재료로 출력합니다.
		printer2.printing(); //Plastic 재료로 출력합니다.
	}
}


제네릭에서 대입된 자료형을 명시하지 않는 경우
GenericPrinter <Powder>와 같이 사용할 자료형을 명시해야 함
자료형을 명시하지 않고 사용할 수 있지만 경고표시가 나타남
반환 형에 따라 강제 형 변환을 해야 함

T extends 클래스
T가 사용될 클래스를 제한하기 위해 사용
위의 코드에서 Material을 상속받지 않은 클래스는 프린터 재료로 사용 불가
Material에 정의된 메서드를 공유할 수 있음

4. 컬렉션 프레임워크(34강)

배열(Array)
같은 형의 데이터 타입을 메모리에 저장하는 선형적 자료구조
논리적 구조와 물리적 구조가 동일함

Linked List
데이터와 링크로 구성

Stack
일반적인 의미-쌓다, 더미
자료구조에서의 의미-선형 자료구조, LIFO(Last In First Out) 후입선출

Queue
일반적인 의미-대기열
자료구조에서의 의미-FIFO(First In First Out) 선입선출

Tree
자료 검색

Binary Search Tree의 특성
유일한 키값
루트 노드의 키 값 기준

Hashing
산술 연산을 이용한 검색방식

5. 컬렉션 프레임워크-ArrayList(35강)

컬렉션 프레임워크
프로그램 구현에 필요한 자료구조(Data Structure)를 구현해놓은 라이브러리
java.util 패키지에 구현되어있음
개발에 소요되는 시간을 절약하면서 최적화된 알고리즘을 사용할 수 있음
여러 인터페이스와 구현 클래스 사용 방법을 이해해야 함

Collection 인터페이스
하나의 객체를 관리하기 위한 메서드가 선언된 인터페이스
하위 List와 Set 인터페이스가 있음
여러 클래스들이 Collection 인터페이스를 구현함

분류 설명
List 인터페이스 순서가 있는 자료 관리, 중복 허용. 이 인터페이스를 구현한 클래스는 ArrayList, Vectior. LinkedList, Stack, Queue 등이 있음
Set 인터페이스 순서가 정해져 있지 않음, 중복을 허용하지 않음. 이 인터페이스를 구현한 클래스는 HashSet, TreeSet 등이 있음


Collection인터페이스에 선언된 주요 메서드

메서드 설명
boolean add(E e) Collection에 객체를 추가합니다.
void clear() Collection의 모든 객체를 제거합니다.
Iterator iterator Collection을 순환할 반복자(iterator)를 반환합니다.
boolean remove(Object o) Collection에 매개변수에 해당하는 인스턴스가 존재하면 제거합니다.
int size() Collection에 있는 요소의 개수를 반환합니다.


List 인터페이스
Collection 하위 인터페이스
객체를 순서에 따라 저장하고 관리하는데 필요한 메서드가 선언된 인터페이스
배열의 기능을 구현하기 위한 인터페이스
ArrayList, Vector, LinkedList 등이 많이 사용됨

ArrayList와 Vector
객체 배열을 구현한 클래스
멀티 스레드 상태에서 리소스에 대한 동기화가 필요한 경우 Vector를 사용
일반적으로 ArrayList를 더 많이 사용
ArrayList에 동기화 기능이 추가돼야 하는 경우

Collections.synchronizedList(new ArrayList<String>());

동기화(synchronization)-두 개의 스레드가 동시에 하나의 리소스에 접근할 때 순서를 맞추어서 데이터에 오류가 발생하지 않도록 함

LinkedList 클래스
논리적으로 순차적인 자료구조가 구현된 클래스
다음 요소에 대한 참조값을 가지고 있음
요소의 추가/삭제에 드는 비용이 배열보다 적음

package collection;
public class Member {
	private int memberId;
	private String memberName;
	
	public Member(int memberId, String memberName) {
		this.memberId = memberId;
		this.memberName = memberName;
	}
	
	public int getMemberId() {
		return memberId;
	}
	
	public void setMemberId(int memberId) {
		this.memberId = memberId;
	}
	
	public String getMemberName() {
		return memberName;
	}
	
	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}
	
	public String toString() {
		return memberName + "회원님의 아이디는 " + memberId + "입니다.";
	}
}

 

package collection.arraylist;

import java.util.ArrayList;
import collection.Member;

public class MemberArrayList {
	private ArrayList<Member> arrayList;
	
	public MemberArrayList() {
		arrayList = new ArrayList<Member>();
	}
	
	public void addMember(Member member) {
		arrayList.add(member);
	}
	
	public boolean removeMember(int memberId) {
		for(int i = 0; i < arrayList.size(); i++) {
			Member member = arrayList.get(i);
			int tempId = member.getMemberId();
			if(memberId == tempId) {
				arrayList.remove(i);
				return true;
			}
		}
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}
	
	public void showAll() {
		for(Member member : arrayList) {
			System.out.println(member);
		}
		System.out.println();
//		System.out.println(arrayList); //전부 출력
	}
}

 

package collection.arraylist;

import collection.Member;

public class MemberArrayListTest {
	public static void main(String[] args) {
		MemberArrayList memberArrayList = new MemberArrayList();
		
		Member member1 = new Member(001, "루카");
		Member member2 = new Member(002, "루이");
		Member member3 = new Member(003, "루팽");
		
		memberArrayList.addMember(member1);
		memberArrayList.addMember(member2);
		memberArrayList.addMember(member3);
		memberArrayList.showAll();
		
		memberArrayList.removeMember(member2.getMemberId());
		memberArrayList.showAll();
	}
}

 

6. 컬렉션 프레임워크-Stack, Queue, HashSet(36강)

Stack과 Queue
Stack과 Queue의 기능은 구현된 클래스가 있지만 ArrayList나 LinkedList를 활용해서 사용할 수도 있음

Stack
Last In First Out(LIFO)
맨 마지막에 추가된 요소가 먼저 꺼내지는 자료구조
게임의 무르기 기능, 최근 자료 추출 등에서 사용

Queue
First In FIrst Out(FIFO)
먼저 저장된 자료가 먼저 꺼내지는 선착순, 대기열 구조

package collection.arraylist;

import java.util.ArrayList;

class MyStack {
	private ArrayList<String> arrayStack = new ArrayList<String>();
	
	public void push(String data) {
		arrayStack.add(data);
	}
	
	public String pop() {
		int len = arrayStack.size();
		if(len == 0) {
			System.out.println("스택이 비었습니다.");
			return null;
		}
		
		return arrayStack.remove(len - 1);
	}
	
	public String peek() {
		int len = arrayStack.size();
		if(len == 0) {
			System.out.println("스택이 비었습니다.");
			return null;
		}
		
		return arrayStack.get(len - 1);
	}
}

public class StackTest {

	public static void main(String[] args) {
		MyStack stack = new MyStack();
		
		stack.push("a");
		stack.push("b");
		stack.push("c");
		
		System.out.println(stack.peek()); //c
		System.out.println(stack.peek()); //c
		System.out.println(stack.peek()); //c
		
		System.out.println(stack.pop()); //c
		System.out.println(stack.pop()); //b
		System.out.println(stack.pop()); //a	
	}
}

 

package collection.arraylist;

import java.util.ArrayList;

class MyQueue {
	
	private ArrayList<String> arrayQueue = new ArrayList<String>();
	
	public void rnQueue(String data) {
		arrayQueue.add(data);
	}
	
	public String deQueue() {
		int len = arrayQueue.size();
		
		if(len == 0) {
			System.out.println("큐가 비었습니다.");
			return null;
		}
		return arrayQueue.remove(0);
	}
}

public class QueueTest {
	public static void main(String[] args) {
	}
}


Iterator 사용하여 순회하기
Collection의 개체를 순회하는 인터페이스
iterator() 메서드 호출

Iterator ir = memberArrayList.iterator();


선언된 메서드

메서드 설명
boolean hashNext() 이후에 요소가 더 있는지를 체크하는 메서드이며, 요소가 있다면 true를 반환합니다.
E next() 다음에 있는 요소를 반환합니다.
public boolean removeMember(int memberId) {
		Iterator<Member> iterator = arrayList.iterator();
		while(iterator.hasNext()) {
			Member member = iterator.next();
			
			int tempId = member.getMemberId();
			if(memberId == tempId) {
				arrayList.remove(member);
				return true;
			}
		}
		
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}


Set 인터페이스
Collection 하위의 인터페이스
중복을 허용하지 않음
아이디, 주민번호 사번 등 유일한 값이나 객체를 관리할 때 사용
List는 순서 기반의 인터페이스지만, Set은 순서가 없음
저장된 순서와 출력 순서는 다를 수 있음
get(i) 메서드가 제공되지 않음

package collection;
public class Member {
	private int memberId;
	private String memberName;
	
	public Member(int memberId, String memberName) {
		this.memberId = memberId;
		this.memberName = memberName;
	}
	
	public int getMemberId() {
		return memberId;
	}
	
	public void setMemberId(int memberId) {
		this.memberId = memberId;
	}
	
	public String getMemberName() {
		return memberName;
	}
	
	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}
	
	public String toString() {
		return memberName + "회원님의 아이디는 " + memberId + "입니다.";
	}

	@Override
	public int hashCode() {
		return memberId;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Member) {
			Member member = (Member)obj;
			
			if(this.memberId == member.memberId) {
				return true;
			}
			else return false;
		}
		return false;
	}
}

 

package collection.hashset;

import java.util.HashSet;
import java.util.Iterator;
import collection.Member;

public class MemberHashSet {
private HashSet<Member> hashSet;
	
	public MemberHashSet() {
		hashSet = new HashSet<Member>();
	}
	
	public void addMember(Member member) {
		hashSet.add(member);
	}
	
	public boolean removeMember(int memberId) {
		Iterator<Member> iterator = hashSet.iterator();
		while(iterator.hasNext()) {
			Member member = iterator.next();
			
			int tempId = member.getMemberId();
			if(memberId == tempId) {
				hashSet.remove(member);
				return true;
			}
		}
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}
	
	public void showAll() {
		for(Member member : hashSet) {
			System.out.println(member);
		}
		System.out.println();
	}
}

 

package collection.hashset;

import collection.Member;

public class MemberHashSetTest {
	public static void main(String[] args) {
		MemberHashSet memberHashSet = new MemberHashSet();
		
		Member member1 = new Member(001, "루카");
		Member member2 = new Member(002, "루이");
		Member member3 = new Member(003, "루팽");
		
		memberHashSet.addMember(member1);
		memberHashSet.addMember(member2);
		memberHashSet.addMember(member3);
		
		memberHashSet.showAll();
		
		Member member4 = new Member(001, "뺑구"); //중복X, 같은Id 추가 안됨
		memberHashSet.addMember(member4);
		memberHashSet.showAll();
	}
}

 

7. 컬렉션 프레임워크-TreeSet, HashMap, TreeMap(37강)

TreeSet 클래스
객체의 정렬에 사용되는 클래스
중복을 허용하지 않으면서 오름차순이나 내림차순으로 객체를 정렬함
내부적으로 이진 검색 트리(binary search tree)로 구현되어 있음
이진 검색 트리에 자료가 저장될 때 비교하여 저장될 위치를 정함
객체 비교를 위해 Comparable이나 Comparator 인터페이스를 구현해야 함

Comparable 인터페이스와 Comparator 인터페이스
정렬 대상이 되는 크래스가 구현해야 하는 인터페이스
Comparable은 compareTo() 메서드를 구현, 매개변수와 객체 자신(this)을 비교
Comparator는 compare() 메서드를 구현, 두 개의 매개 변수를 비교, TreeSet 생성자에 Comparator가 구현된 객체를 매개변수로 전달

TreeSet<Member> treeSet = new TreeSet<Member>(new Member());

일반적으로 Comparable을 더 많이 사용
이미 Comparable이 구현된 경우 Comparator를 이용하여 다른 정렬 방식을 정의할 수 있음

package collection;

import java.util.Comparator;

public class Member implements Comparable<Member>, Comparator<Member> {
	private int memberId;
	private String memberName;
	
	public Member() {}
	
	public Member(int memberId, String memberName) {
		this.memberId = memberId;
		this.memberName = memberName;
	}
	
	public int getMemberId() {
		return memberId;
	}
	
	public void setMemberId(int memberId) {
		this.memberId = memberId;
	}
	
	public String getMemberName() {
		return memberName;
	}
	
	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}
	
	public String toString() {
		return memberName + "회원님의 아이디는 " + memberId + "입니다.";
	}

	@Override
	public int hashCode() {
		return memberId;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Member) {
			Member member = (Member)obj;
			
			if(this.memberId == member.memberId) {
				return true;
			}
			else return false;
		}
		return false;
	}

	@Override
	public int compareTo(Member member) { //Comparable
		return (this.memberId - member.memberId); //오름차순
//		return (this.memberId - member.memberId) * (-1); //내림차순
//		return (this.memberName.compareTo(member.memberName)); //오름차순
//		return (this.memberName.compareTo(member.memberName)) * (-1); //내림차순
	}

	@Override
	public int compare(Member member1, Member member2) { //Comparator
		return (member1.memberId - member2.memberId); //오름차순
	}
}

 

package collection.treeset;

import java.util.TreeSet;
import java.util.Iterator;
import collection.Member;

public class MemberTreeSet {
private TreeSet<Member> treeSet;
	
	public MemberTreeSet() {
		treeSet = new TreeSet<Member>();
//		treeSet = new TreeSet<Member>(new Member()); /Comparator를 쓸 경우
	}
	
	public void addMember(Member member) {
		treeSet.add(member);
	}
	
	public boolean removeMember(int memberId) {
		Iterator<Member> iterator = treeSet.iterator();
		while(iterator.hasNext()) {
			Member member = iterator.next();
			
			int tempId = member.getMemberId();
			if(memberId == tempId) {
				treeSet.remove(member);
				return true;
			}
		}
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}
	
	public void showAll() {
		for(Member member : treeSet) {
			System.out.println(member);
		}
		System.out.println();
	}
}

 

package collection.treeset;

import collection.Member;

public class MemberTreeSetTest {
	public static void main(String[] args) {
		MemberTreeSet memberTreeSet = new MemberTreeSet();
		
		Member member1 = new Member(001, "루카");
		Member member2 = new Member(002, "루이");
		Member member3 = new Member(003, "루팽");
		
		memberTreeSet.addMember(member1);
		memberTreeSet.addMember(member2);
		memberTreeSet.addMember(member3);
		
		memberTreeSet.showAll();
	}
}


Map 인터페이스
key-value pair의 객체를 관리하는데 필요한 메서드가 정의됨
key는 중복될 수 없음
검색을 위한 자료 구조
key를 이용하여 값을 저장하거나 검색, 삭제할 때 사용하면 편리
내부적으로 hash 방식으로 구현됨

index = hash(key) //index는 저장위치

key가 되는 객체는 객체의 유일성 여부를 알기 위해 equals()와 hashCode() 메서드를 재정의함

HashMap 클래스
Map인터페이스를 구현한 클래스 중 가장 일반적으로 사용하는 클래스
Vector처럼 동기화를 제공함
여러 메서드를 활용하여 pair자료를 쉽고 빠르게 관리할 수 있음

package collection.hashmap;

import java.util.HashMap;
import java.util.Iterator;
import collection.Member;

public class MemberHashMap {
	private HashMap<Integer, Member> hashMap;
	
	public MemberHashMap() {
		hashMap = new HashMap<Integer, Member>();
	}
	
	public void addMember(Member member) {
		hashMap.put(member.getMemberId(), member);
	}
	
	public boolean removeMember(int memberId) {
		if(hashMap.containsKey(memberId)) {
			hashMap.remove(memberId);
			return true;
		}
		
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}
	
	public void showAllMember() {
		Iterator<Integer> ir = hashMap.keySet().iterator();
		
		while(ir.hasNext()) {
			int key = ir.next();
			
			Member member = hashMap.get(key);
			System.out.println(member);
		}
	}
}

 

package collection.hashmap;

import collection.Member;
import collection.treeset.MemberTreeSet;

public class MemberHashMapTest {
	public static void main(String[] args) {
		MemberTreeSet memberHashMap = new MemberTreeSet();
		
		Member member1 = new Member(001, "루카");
		Member member2 = new Member(002, "루이");
		Member member3 = new Member(003, "루팽");
		
		memberHashMap.addMember(member1);
		memberHashMap.addMember(member2);
		memberHashMap.addMember(member3);
		
		memberHashMap.showAll();
		
		memberHashMap.removeMember(1);
		memberHashMap.showAll();
	}
}


TreeMap 클래스
key 객체를 정렬하여 key-value를 pair로 관리하는 클래스
key에 사용되는 클래스에 COmparable, Comparator인터페이스를 구현
java의 많은 클래스들은 이미 Comparable이 구현되어 있음
구현된 클래스를 key로 사용하는 경우는 구현할 필요 없음

package collection.treemap;

import java.util.TreeMap;
import java.util.Iterator;
import collection.Member;

public class MemberTreeMap {
	private TreeMap<Integer, Member> treeMap;
	
	public MemberTreeMap() {
		treeMap = new TreeMap<Integer, Member>();
	}
	
	public void addMember(Member member) {
		treeMap.put(member.getMemberId(), member);
	}
	
	public boolean removeMember(int memberId) {
		if(treeMap.containsKey(memberId)) {
			treeMap.remove(memberId);
			return true;
		}
		
		System.out.println(memberId + "가 존재하지 않습니다.");
		return false;
	}
	
	public void showAllMember() {
		Iterator<Integer> ir = treeMap.keySet().iterator();
		
		while(ir.hasNext()) {
			int key = ir.next();
			
			Member member = treeMap.get(key);
			System.out.println(member);
		}
	}
}

 

package collection.treemap;

import collection.Member;

public class MemberTreeMapTest {
	public static void main(String[] args) {
		MemberTreeMap memberTreeMap = new MemberTreeMap();
		
		Member member1 = new Member(001, "루카");
		Member member2 = new Member(002, "루이");
		Member member3 = new Member(003, "루팽");
		
		memberTreeMap.addMember(member1);
		memberTreeMap.addMember(member2);
		memberTreeMap.addMember(member3);
		
		memberTreeMap.showAllMember();
	}
}