Java공부(코딩)

코딩초보의 자바(Java)공부 31일차 { 순회, 정렬, 전체정리 }

동곤일상 2025. 1. 17. 16:19
반응형
어느덧 한달 차가 지나가네요..
전 다시 처음부터 복습하며
DB공부를 해볼까합니다..

순회 - 자바가제공하는 Iterable ,Iterator

Iterable, Iterator
Iterable : "반복 가능한"이라는 뜻이다.
Iterator : "반복자"라는 뜻이다.

 

자바가 제공하는 컬렉션 프레임워크의 모든 자료 구조는 Iterable 과 Iterator 를 사용해서 편리하고 일
관된 방법으로 순회할 수 있다. 물론 Iterable 을 구현하기 때문에 향상된 for문도 사용할 수 있다.

 

코드를 통해 한번 보자

Iterator , Iterable 은 인터페이스이다. 따라서 다형성을 적극 활용할 수 있다.

package javaBasic2.collection.iterable;

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

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

		ArrayList<Object> arrayList = new ArrayList<>();
		arrayList.add(1);
		arrayList.add(2);
		arrayList.add(3);
		
		HashSet<Object> hashSet = new HashSet<>();
		hashSet.add(1);
		hashSet.add(2);
		hashSet.add(3);
		hashSet.add(4);
		
		printAll(arrayList.iterator());
		printAll(hashSet.iterator());
		
		forEach(arrayList);
		forEach(hashSet);
	}

	
	private static void forEach(Iterable<Object> iterable) {
		System.out.println("iterableClass : "+iterable.getClass());
		for (Object object : iterable) {
			System.out.println(object);
			
		}
		
		
	}


	private static void printAll(Iterator<Object> iterator) {
		System.out.println("iteratorClass :" +iterator.getClass());
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		
	}

}

iteratorClass :class java.util.ArrayList$Itr

1

2

3

iteratorClass :class java.util.HashMap$KeyIterator

1

2

3

4

iterableClass : class java.util.ArrayList

1

2

3

iterableClass : class java.util.HashSet

1

2

3

4


정렬 - Comparable , Comparator

 

비교자 - Comparator
그런데 정렬을 할 때 1, 2, 3 순서가 아니라 반대로 3, 2, 1로 정렬하고 싶다면 어떻게 해야할까?
이때는 비교자( Comparator )를 사용하면 된다. 이름 그대로 두 값을 비교할 때 비교 기준을 직접 제공할 수 있다.

 

public interface Comparator<T> {
 int compare(T o1, T o2);
}
```
두 인수를 비교해서 결과 값을 반환하면 된다.
첫 번째 인수가 더 작으면 음수, 예( -1 )
두 값이 같으면 0
첫 번째 인수가 더 크면 양수, 예( 1 )

 

package javaBasic2.collection.comparable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class SortMain {
	public static void main(String[] args) {
		Integer[] a = {1,5,2,12};
		System.out.println("원본배열");
		System.out.println(Arrays.toString(a));
		
		Arrays.sort(a,new AscComapator());
		System.out.println(Arrays.toString(a));
		
		Arrays.sort(a,new DescComapator());
		System.out.println(Arrays.toString(a));
		
		

	}
	static class AscComapator implements Comparator<Integer>{
		public AscComapator() {
			System.out.println("오름차순");
		}
		@Override
		public int compare(Integer o1, Integer o2) {
			System.out.println("o1 : "+o1+" o2 : "+o2);
			return (o1<o2)?-1 : (01==02)? 0 : 1;
		}
		
	}
	
	static class DescComapator implements Comparator<Integer>{
		public DescComapator() {
			System.out.println("내림차순");
		}
		
		@Override
		public int compare(Integer o1, Integer o2) {
			System.out.println("o1 : "+o1+" o2 : "+o2);
			return ((o1<o2)?-1 : (01==02)? 0 : 1)*-1;
		}
		
	}

	

}

 

Arrays.sort() 를 사용할 때 비교자( Comparator )를 넘겨주면 알고리즘에서 어떤 값이 더 큰지 두 값을 비교할때, 비교자를 사용한다.
Arrays.sort(array, new AscComparator())
Arrays.sort(array, new DescComparator())

 

정렬을 반대로
new AscComparator().reversed()

new DescComparator()와 같은결과가 나옴


정렬2 - Comparable , Comparator

자바가 기본으로 제공하는 Integer , String 같은 객체를 제외하고 MyUser 와 같이 직접 만든 객체를 정렬하려면
어떻게 해야 할까?

이때는 Comparable 인터페이스를 구현해보자

```java
public interface Comparable<T> {
 public int compareTo(T o);
}

 

package javaBasic2.collection.comparable;

public class Myuser implements Comparable<Myuser>{
	
	private String id;
	private int age;

	public Myuser(String id , int age) {
		this.id = id;
		this.age = age;
	}
	public int getAge() {
		return this.age;
	}
	
	@Override
	public int compareTo(Myuser o) {
		return this.age<o.age?-1 : (this.age==o.age)? 0 :1;
	}
	
	@Override
	public String toString() {
		return "Myuser [id=" + id + ", age=" + age + "]";
	}
	
	

}

 

package javaBasic2.collection.comparable;

import java.util.Arrays;

public class MyuserMain {
	public static void main(String[] args) {
		Myuser myuser1 = new Myuser("동곤자바", 31);
		Myuser myuser2 = new Myuser("비교자", 3);
		Myuser myuser3 = new Myuser("참 쉽죠", 10);
		Myuser myuser4 = new Myuser("!!!", 1);
		
		Myuser[] a = {myuser1,myuser2,myuser3,myuser4};
		System.out.println("정렬 전");
		System.out.println(Arrays.toString(a));
		
		System.out.println("정렬 후 (오름차순)");
		Arrays.sort(a);
		System.out.println(Arrays.toString(a));
	}

}

정렬 전
[Myuser [id=동곤자바, age=31], Myuser [id=비교자, age=3], Myuser [id=참 쉽죠, age=10], Myuser [id=!!!, age=1]]
정렬 후 (오름차순)
[Myuser [id=!!!, age=1], Myuser [id=비교자, age=3], Myuser [id=참 쉽죠, age=10], Myuser [id=동곤자바, age=31]]

Arrays.sort(array)
기본 정렬을 시도한다. 이때는 객체가 스스로 가지고 있는 Comparable 인터페이스를 사용해서 비교한다.
MyUser 가 구현한 대로 나이( age ) 오름차순으로 정렬된 것을 확인할 수 있다.

 

Comparable을 구현함으로써

객체도 정렬이 가능해짐!!!

 


아이디를 기준으로도 정렬을만들 수 있다.

package javaBasic2.collection.comparable;

import java.util.Comparator;

public class Idcomparator implements Comparator<Myuser>{

	@Override
	public int compare(Myuser o1, Myuser o2) {
		return o1.getId().compareTo(o2.getId());
	}
}
package javaBasic2.collection.comparable;

import java.util.Arrays;

public class MyuserMain {
	public static void main(String[] args) {
		Myuser myuser1 = new Myuser("a", 31);
		Myuser myuser2 = new Myuser("b", 3);
		Myuser myuser3 = new Myuser("d", 10);
		Myuser myuser4 = new Myuser("c", 1);
		
		Myuser[] a = {myuser1,myuser2,myuser3,myuser4};
		System.out.println("정렬 전");
		System.out.println(Arrays.toString(a));
		
		System.out.println("age정렬 후 (오름차순)");
		Arrays.sort(a);
		System.out.println(Arrays.toString(a));
		
		System.out.println("Id정렬(Idcomparator)");
		Arrays.sort(a,new Idcomparator());
		System.out.println(Arrays.toString(a));
	}
}

정렬 전
[Myuser [id=a, age=31], Myuser [id=b, age=3], Myuser [id=d, age=10], Myuser [id=c, age=1]]
age정렬 후 (오름차순)
[Myuser [id=c, age=1], Myuser [id=b, age=3], Myuser [id=d, age=10], Myuser [id=a, age=31]]
Id정렬(Idcomparator)
[Myuser [id=a, age=31], Myuser [id=b, age=3], Myuser [id=c, age=1], Myuser [id=d, age=10]]

 

Arrays.sort(array, Comparator)
기본 정렬이 아니라 정렬 방식을 지정하고 싶다면 Arrays.sort 의 인수로 비교자( Comparator )를 만들어서 넘겨
주면 된다. 이렇게 비교자를 따로 전달하면 객체가 기본으로 가지고 있는 Comparable 을 무시하고, 별도로 전달한 비
교자를 사용해서 정렬한다.

 

Comparable, Comparator 정리
객체의 기본 정렬 방법은 객체에 Comparable 를 구현해서 정의한다. 

이렇게 하면 객체는 이름 그대로 비교할 수 있는객체가 되고

기본 정렬 방법을 가진다.

그런데 기본 정렬 외에 다른 정렬 방법을 사용해야 하는 경우 비교자( Comparator )를 별도로 구현해서 정렬 메서드에 전달하면 된다. 

이 경우 전달한 Comparator 가 항상 우선권을 가진다.
자바가 제공하는 Integer , String 같은 기본 객체들은 대부분 Comparable 을 구현해 두었다.


 

정렬2 - Comparable , Comparator

 

정렬은 배열뿐만아니라 List같은 자료구조에도활용가능

package javaBasic2.collection.comparable;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;

public class SortMain2 {
	public static void main(String[] args) {
		Myuser myuser1 = new Myuser("a", 31);
		Myuser myuser2 = new Myuser("b", 3);
		Myuser myuser3 = new Myuser("d", 10);
		Myuser myuser4 = new Myuser("c", 1);
		
		ArrayList<Myuser> list = new ArrayList<>();
		list.add(myuser1);
		list.add(myuser2);
		list.add(myuser3);
		list.add(myuser4);
		System.out.println("원본 리스트");
		System.out.println(list+"\n");
		
		System.out.println("기본정렬(Comparable)");
		list.sort(null);
		System.out.println(list);
		
		System.out.println("\nIdComparable정렬");
		list.sort(new Idcomparator());
		System.out.println(list);
	}

}

 

 

원본 리스트

[Myuser [id=a, age=31], Myuser [id=b, age=3], Myuser [id=d, age=10], Myuser [id=c, age=1]]

 

기본정렬(Comparable)

[Myuser [id=c, age=1], Myuser [id=b, age=3], Myuser [id=d, age=10], Myuser [id=a, age=31]]

 

IdComparable정렬

[Myuser [id=a, age=31], Myuser [id=b, age=3], Myuser [id=c, age=1], Myuser [id=d, age=10]]

 

list.sort(null)
별도의 비교자가 없으므로 Comparable 로 비교해서 정렬한다.
자연적인 순서로 비교한다.

 

Collections.sort(list, new IdComparator())
별도의 비교자로 비교하고 싶다면 다음 인자에 비교자를 넘기면 된다.
하지만 이 방식보다는 객체 스스로 정렬 메서드를 가지고 있는 list.sort() 사용을 더 권장한다.

 참고로 둘의결과는 같다.

 

list.sort(new IdComparator())
전달한 비교자로 비교한다.

 


Tree구조와 정렬

이진 탐색 트리는 데이터를 저장할 때 왼쪽 노드에 저장해야 할 지, 오른쪽 노드에 저장해야 할 지 비교가 필요하다.
따라서 TreeSet , TreeMap 은 Comparable 또는 Comparator 가 필수이다.

 

package javaBasic2.collection.comparable;

import java.util.Set;
import java.util.TreeSet;

public class SortMain3 {
	public static void main(String[] args) {
		Myuser myuser1 = new Myuser("a", 31);
		Myuser myuser2 = new Myuser("b", 3);
		Myuser myuser3 = new Myuser("d", 10);
		Myuser myuser4 = new Myuser("c", 1);
		
		Set<Myuser> set = new TreeSet<>();
		set.add(myuser1);
		set.add(myuser2);
		set.add(myuser3);
		set.add(myuser4);
		
		System.out.println("기본정렬(Comparable)");
		System.out.println(set);
		
		Set<Myuser> set2 = new TreeSet<>(new Idcomparator());
		set2.add(myuser1);
		set2.add(myuser2);
		set2.add(myuser3);
		set2.add(myuser4);
		System.out.println("\nIdComparator정렬");
		System.out.println(set2);
		
	

	}

}

 

new TreeSet<>() 
TreeSet 을 생성할 때 별도의 비교자를 제공하지 않으면 객체가 구현한 Comparable 을 사용한다.


new TreeSet<>(new IdComparator()) ```
TreeSet 을 생성할 때 별도의 비교자를 제공하면 Comparable 대신 

비교자( Comparator )를 사용해서 정렬한다.

 


컬렉션유틸

컬렉션을 편리하게다룰 수 있는 다양한기능알아보기!!

 

package javaBasic2.collection.utils;

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

public class CollectionSortMain {
	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(5);
		list.add(4);
		list.add(12);
		list.add(87);
		list.add(43);
		list.add(23);
		System.out.println("리스트 : "+list);
		Integer max = Collections.max(list);
		Integer min = Collections.min(list);
		System.out.println("최솟값 : "+min);
		System.out.println("최대값 : "+max);

		Collections.shuffle(list);
		System.out.println("shuffle : "+list);

		Collections.sort(list);
		System.out.println("sort : "+list);

		Collections.reverse(list);
		System.out.println("reverse : "+list);



	}

}

리스트 : [1, 5, 4, 12, 87, 43, 23]

최솟값 : 1

최대값 : 87

shuffle : [43, 5, 12, 1, 4, 23, 87]

sort : [1, 4, 5, 12, 23, 43, 87]

reverse : [87, 43, 23, 12, 5, 4, 1]

 

Collections 정렬 관련 메서드
max : 정렬 기준으로 최대 값을 찾아서 반환한다.
min : 정렬 기준으로 최소 값을 찾아서 반환한다.
shuffle : 컬렉션을 랜덤하게 섞는다.
sort : 정렬 기준으로 컬렉션을 정렬한다.
reverse : 정렬 기준의 반대로 컬렉션을 정렬한다.

 


편리한 컬렉션 생성

package javaBasic2.collection.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class OfMain {
	public static void main(String[] args) {
		List<Integer>list = List.of(1,2,3);
		Set<Integer> set = Set.of(1,5,6,2);
		 Map<String, Integer> map = Map.of("id1",22,"id2",4);
		System.out.println(list);
		System.out.println(set);
		System.out.println(map);
		
		System.out.println(list.getClass());//불변객체
//		list.add(4);
		
		System.out.println("불변-->가변");
		ArrayList<Integer> list2 = new ArrayList<>(list);
		list2.add(4);
		System.out.println(list2);
		
		System.out.println("가변-->불변");
		Collection<Integer> list3 = Collections.unmodifiableCollection(list2);
//		list3.add(5);
		System.out.println(list3);
		
		

	}

}

[1, 2, 3]

[2, 1, 6, 5]

{id2=4, id1=22}

class java.util.ImmutableCollections$ListN

불변-->가변

[1, 2, 3, 4]

가변-->불변

[1, 2, 3, 4]

 

list.of()를사용하면 불변컬렉션이만들어짐

변경할수 없음!!!

 

가변-->불변 : Collections.unmodifiablexxxx() 를 사용(xxx를 여기선 collection사용)

불변->가변 : new ArrayList<>(list);


멀티스레드 동기화

package javaBasic2.collection.utils;

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

public class SyncMain {
	public static void main(String[] args) {
		ArrayList<Object> list = new ArrayList<Object>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		System.out.println("!!list class!!");
		System.out.println(list.getClass());
		List<Object> syncList = Collections.synchronizedList(list);
		System.out.println();
		System.out.println("!!synchronizedList.class!!");
		System.out.println(syncList.getClass());
	}
}

!!list class!!

class java.util.ArrayList

 

!!synchronizedList.class!!

class java.util.Collections$SynchronizedRandomAccessList

 

Collections.synchronizedList 를 사용하면 일반 리스트를

멀티스레드 상황에서 동기화 문제가 발생하지 않는 안전한 리스트로 만들 수 있다.
동기화 작업으로 인해 일반 리스트보다 성능은 더 느리다.
이 부분은 멀티스레드를 학습해야 이해할 수 있으므로 지금은 이런 것이 있다 정도만 참고하고 넘어가자.


컬렉션 프레임워크 전체정리

 

Collection 인터페이스의 필요성


Collection 인터페이스는 자바 컬렉션 프레임워크의 가장 기본적인 인터페이스로, 자바에서 데이터 그룹을 다루는
데 필요한 가장 기본적인 메서드들을 정의한다.

. List , Set , Queue 와 같은 더 구체적인 컬렉션 인터페이스들은 모두 Collection 인터페이스를 확장
(extend)하여, 공통된 메서드들을 상속받고 추가적인 기능이나 특성을 제공한다. 

이러한 설계는 자바 컬렉션 프레임워크의 일관성과 재사용성을 높여준다.


일관성: 모든 컬렉션 타입들이 Collection 인터페이스를 구현함으로써, 모든 컬렉션들이 기본적인 동작을 공
유한다는 것을 보장한다. 이는 개발자가 다양한 타입의 컬렉션을 다룰 때 일관된 방식으로 접근할 수 있게 해준다.
재사용성: Collection 인터페이스에 정의된 메서드들은 다양한 컬렉션 타입들에 공통으로 적용된다. 이는 코
드의 재사용성을 높이고, 유지 보수를 용이하게 한다.
확장성: 새로운 컬렉션 타입을 만들 때 Collection 인터페이스를 구현함으로써, 기존에 정의된 알고리즘과 도
구를 사용할 수 있게 된다. 이는 프레임워크의 확장성을 향상시킨다.
다형성: Collection 인터페이스를 사용함으로써, 다양한 컬렉션 타입들을 같은 타입으로 다룰 수 있다. 이는
다형성을 활용해서 유연한 코드를 작성할 수 있게 해준다.

 

 

Collection 인터페이스의 주요 메서드


Collection 인터페이스에는 다음과 같은 주요 메서드들이 포함된다.
add(E e) : 컬렉션에 요소를 추가한다.
remove(Object o) : 주어진 객체를 컬렉션에서 제거한다.
size() : 컬렉션에 포함된 요소의 수를 반환한다.
isEmpty() : 컬렉션이 비어 있는지 확인한다.
contains(Object o) : 컬렉션이 특정 요소를 포함하고 있는지 확인한다.
iterator() : 컬렉션의 요소에 접근하기 위한 반복자를 반환한다.
clear() : 컬렉션의 모든 요소를 제거한다

 

Collection  Map 을 제외한 모든 컬렉션 타입의 부모이다. 따라서 모든 컬렉션을 받아서 유연하게 처리할 수 있

 

대표적으로 컬렉션 인터페이스는 iterator 를 제공한다. 따라서 데이터를 단순히 순회할 목적이라면 Collection
을 사용하면 모든 컬렉션 타입의 데이터를 순회할 수 있다.

 


인터페이스


자바 컬렉션 프레임워크의 핵심 인터페이스는 다음과 같다:


Collection: 단일 루트 인터페이스로, 모든 컬렉션 클래스가 이 인터페이스를 상속받는다.
List , Set , Queue 등의 인터페이스가 여기에 포함된다.


List: 순서가 있는 컬렉션을 나타내며, 중복 요소를 허용한다. 인덱스를 통해 요소에 접근할 수 있다.
예: ArrayList , LinkedList


Set: 중복 요소를 허용하지 않는 컬렉션을 나타낸다. 특정 위치가 없기 때문에 인덱스를 통해 요소에 접근할 수 없
다. 예: HashSet , LinkedHashSet , TreeSet


Queue: 요소가 처리되기 전에 보관되는 컬렉션을 나타낸다.
예: ArrayDeque , LinkedList , PriorityQueue


Map: 키와 값 쌍으로 요소를 저장하는 객체이다. Map 은 Collection 인터페이스를 상속받지 않는다.
예: HashMap , LinkedHashMap , TreeMap

 

구현

자바는 각 인터페이스의 여러 구현을 제공한다:
List: ArrayList 는 내부적으로 배열을 사용하며, LinkedList 는 연결 리스트를 사용한다.


Set: HashSet 은 해시 테이블을, LinkedHashSet 은 해시 테이블과 연결 리스트를, TreeSet 은 레드-블랙
트리를 사용한다.


Map: HashMap 은 해시 테이블을, LinkedHashMap 은 해시 테이블과 연결 리스트를, TreeMap 은 레드-블랙
트리를 사용한다.


Queue: LinkedList 는 연결 리스트를 사용한다. ArrayDeque 는 배열 기반의 원형 큐를 사용한다. 대부분
의 경우 ArrayDeque 가 빠르다.


선택 가이드


순서가 중요하고 중복이 허용되는 경우List 인터페이스를 사용하자. ArrayList 가 일반적인 선택이지만, 추
가/삭제 작업이 앞쪽에서 빈번한 경우에는 LinkedList 가 성능상 더 좋은 선택이다.


중복을 허용하지 않고 순서가 중요하지 않은 경우HashSet 을 사용하자. 순서를 유지해야 하면
LinkedHashSet 을, 정렬된 순서가 필요하면 TreeSet 을 사용하자

 

요소를 키-값 쌍으로 저장하려는 경우: Map 인터페이스를 사용하자. 순서가 중요하지 않다면 HashMap 을, 순서
를 유지해야 한다면 LinkedHashMap 을, 정렬된 순서가 필요하면 TreeMap 을 사용하자


요소를 처리하기 전에 보관해야 하는 경우: Queue , Deque 인터페이스를 사용하자. 스택, 큐 구조 모두
ArrayDeque 를 사용하는 것이 가장 빠르다.

 


실무 선택 가이드

List 의 경우 대부분 ArrayList 를 사용한다.
Set 의 경우 대부분 HashSet 을 사용한다.
Map 의 경우 대부분 HashMap 을 사용한다.
Queue 의 경우 대부분 ArrayDeque 를 사용한다.


 

예제

요구사항
카드( Card )는 1 ~ 13까지있다. 각 번호당 다음 4개의 문양이 있다.
♠: 스페이드
♥: 하트
: 다이아
♣: 클로버
예) 1(♠), 1(♥), 1( ), 1(♣), 2(♠), 2(♥), 2(   , 2(♣) ... 13(♠), 13(♥), 13( ), 13(♣)
따라서 13 * 4 = 총 52장의 카드가 있다.
52장의 카드가 있는 카드 뭉치를 덱( Deck )이라 한다.


2명의 플레이어( Player )가 게임을 진행한다.


게임을 시작하면 다음 순서를 따른다.
1. 덱에 있는 카드를 랜덤하게 섞는다.


2. 각 플레이어는 덱에서 카드를 5장씩 뽑는다

.3. 각 플레이어는 5장의 카드를 정렬된 순서대로 보여준다. 

정렬 기준은 다음과 같다.작은 숫자가 먼저 나온다.


같은 숫자의 경우 ♠, ♥, ◆, ♣ 순으로 정렬한다. ♠가 가장 먼저 나온다.
예) 1(♠), 1(♥), 2( ), 3(♣) 순서로 출력된다.
4. 카드 숫자의 합계가 큰 플레이어가 승리한다.
게임을 단순화 하기 위해 숫자만 출력한다.
합계가 같으면 무승부이다.
실행 결과 예시 ```
플레이어1의 카드: [2(♠), 7(♥), 7(♦), 8(♣), 13(♠)], 합계: 37
플레이어2의 카드: [1(♠), 1(♣), 6(♠), 9(♠), 9(♣)], 합계: 26
플레이어1 승리 ```
```
플레이어1의 카드: [2(♦), 3(♠), 6(♥), 10(♣), 13(♦)], 합계: 34
플레이어2의 카드: [2(♠), 4(♣), 5(♠), 11(♣), 12(♥)], 합계: 34
무승부 ```
참고
스페이드, 하트 같은 아이콘을 직접 사용하기 어려운 경우 다음과 같이 \ (백슬래시 backslash)와 함께 다음 코드를 적
어주면 아이콘을 출력할 수 있다.
"\u2660" : 스페이드(♠)
"\u2665" : 하트(♥)
"\u2666" : 다이아몬드( )
"\u2663" : 클로버(♣)
예) System.out.println("\u2660")
이 문제는 정해진 정답이 없다. 실행 결과 예시를 참고하되, 자유롭게 풀면 된다.
CardGameMain 에 main() 메서드를 만들고 시작하자. 필요하면 클래스를 추가해도 된다.

 

package javaBasic2.collection.comparable.test;

public enum Suit {
	SPADE("\u2660"),
	HEART("\u2665"),
	DIAMOND("\u2666"),
	CLUB("\u2663");
	
	private String a;
	
	Suit(String a) {
		this.a = a;
	}
	
	String getIcon(){
		return this.a;
	}
	

}
package javaBasic2.collection.comparable.test;

public class Card implements Comparable<Card> {
	
	private final int rank;
	private final Suit suit;
	
	public Card(int rank, Suit suit) {
		this.rank = rank;
		this.suit = suit;
	}
	
	public int getRank() {
		return rank;
	}

	public Suit getSuit() {
		return suit;
	}

	@Override
	public int compareTo(Card o) {
		if(this.rank != o.rank) { 
			return Integer.compare(this.rank, o.rank);
		}
		else { //카드의숫자가같다면 문양으로비교
			return this.suit.compareTo(o.suit);
		}
	}

	@Override
	public String toString() {
		return "Card [rank=" + rank + ", suit=" + suit + "]";
	}
	
	
	

}

Suit 는 ENUM 타입이다. 

스페이드, 하트 등의 문양의 순서는 변하지 않는다고 가정하고, ENUM의 기본 순서를 사용한다.
ENUM 타입은 compareTo() 가 열거형의 순서인 ordinal 로 구현되어 있다. 그리고 ENUM의
compareTo() 메서드는 final 선언되어 있어서 재정의 할 수 없다.

 

package javaBasic2.collection.comparable.test;

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

public class Deck {
	List<Card> card = new ArrayList<Card>();
	
	public Deck() {
		initCard();
		sufflecard();
	}
	private void initCard() {
		for (int i = 1; i <= 13; i++) {
			for(Suit suit : Suit.values()) {
				card.add(new Card(i, suit));//리스트에 13*4장의 카드를집어넣음(카드팩만들기)
			}
		}
	}
	private void sufflecard() {
		Collections.shuffle(card);//무작위로섞기
	}
	public Card drawCard() {
		 return card.remove(0); //카드꺼내기(앞에서부터)
		 }
	

}

Deck객체를 생성하면

(13*4)장의카드가생성 + 무작위로섞음

 

package javaBasic2.collection.comparable.test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Player {
	
	private String name;
	private List<Card> hand;
	
	public Player(String name) {
		this.name = name;
		this.hand = new ArrayList<>();
	}
	public String  getName() {
		return this.name;
	}
	
	public void drawCard(Deck deck) {
		hand.add(deck.drawCard());
	}
	public int rankSum() {
		int value=0;
		for (Card card : hand) {
			value+=card.getRank();
		}
		return value;
	}
	
	public void showHand() {
		hand.sort(null);
		System.out.println(name+"의 덱 :"+hand+" 점수 : "+rankSum());
	}
	

}

drawCard :  hand리스트에  deck한장(점수,이름) 을 뽑아서 넣음

rankSum :  hand에 들어있는 숫자들을 모두 합해서 반환

showHand :  카드를 정렬 후 출력

 

package javaBasic2.collection.comparable.test;

public class CardGameMain {

	public static void main(String[] args) {
		Deck deck = new Deck();
		Player player1 = new Player("동곤자바");
		Player player2 = new Player("화이팅");

		for (int i = 0; i < 5; i++) {
			player1.drawCard(deck);//deck안에 셔플기능이있음
			player2.drawCard(deck);
		}

		player1.showHand();
		player2.showHand();
		int winner = getWinner(player1, player2);
		switch(winner) {
		case -1 : System.out.println(player2.getName()+"승리");
		break;
		case 0 : System.out.println("동점");
		break;
		case 1 : System.out.println(player1.getName()+"승리");
		break;
		}
	}

	private static int getWinner(Player p1, Player p2) {
		return p1.rankSum()>p2.rankSum() ? 1:
			(p1.rankSum()==p2.rankSum())? 0:-1;

	}
}

deck 5장을 뽑고

결과를 출력 후

 

rankSum을 비교해

승자 무승부 패자를 가려냄!