* 이 포스팅의 연습문제는 남궁성 선생님의 자바의 정석에 수록된 문제이며 정답 및 해설은 본인의 의견입니다.
* 연습문제 PDF파일은 아래 남궁성 선생님의 GitHub에서 다운 받으실 수 있습니다.
https://github.com/castello/javajungsuk3
<문제1>
[11-1] 다음은 정수집합 1,2,3,4와 3,4,5,6의 교집합, 차집합, 합집합을 구하는 코드이다.
코드를 완성하여 실행결과와 같은 결과를 출력하시오.
[Hint] ArrayList클래스의 addAll(), removeAll(), retainAll()을 사용하라.
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
|
import java.util.*;
class Exercise11_1 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
ArrayList kyo = new ArrayList(); // 교집합
ArrayList cha = new ArrayList(); // 차집합
ArrayList hap = new ArrayList(); // 합집합
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list2.add(3);
list2.add(4);
list2.add(5);
list2.add(6);
/*
* (1) 알맞은 코드를 넣어 완성하시오.
*/
System.out.println("list1=" + list1);
System.out.println("list2=" + list2);
System.out.println("kyo=" + kyo);
System.out.println("cha=" + cha);
System.out.println("hap=" + hap);
}
}
|
cs |
[실행결과]
list1=[1, 2, 3, 4]
list2=[3, 4, 5, 6]
kyo=[3, 4]
cha=[1, 2]
hap=[1, 2, 3, 4, 5, 6]
<나의 풀이>
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
|
import java.util.ArrayList;
import java.util.HashSet;
public class Exercise11_1 {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
ArrayList kyo = new ArrayList(); // 교집합
ArrayList cha = new ArrayList(); // 차집합
ArrayList hap = new ArrayList(); // 합집합
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list2.add(3);
list2.add(4);
list2.add(5);
list2.add(6);
// 교집합 방법1)
for (int i = 0; i < list1.size(); i++) {
if (list2.contains(list1.get(i))) {
kyo.add(list1.get(i));
}
}
// 교집합 방법2)
ArrayList kyo2 = new ArrayList(list1);
kyo2.retainAll(list2);
// 차집합 방법1)
for (int i = 0; i < list1.size(); i++) {
if (!(list2.contains(list1.get(i))))
cha.add(list1.get(i));
}
// 차집합 방법2)
ArrayList cha2 = new ArrayList(list1);
cha2.removeAll(list2);
// 합집합 방법1)
HashSet setHap = new HashSet(hap);
setHap.addAll(list1);
setHap.addAll(list2);
hap = new ArrayList(setHap);
// 합집합 방법2)
ArrayList hap2 = new ArrayList();
for (int i = 0; i < list1.size(); i++) {
if (!(list2.contains(list1.get(i))))
hap2.add(list1.get(i));
}
hap2.addAll(list2);
System.out.println("list1=" + list1);
System.out.println("list2=" + list2);
System.out.println("kyo방법1=" + kyo);
System.out.println("kyo방법2=" + kyo);
System.out.println("cha방법1=" + cha);
System.out.println("cha방법2=" + cha2);
System.out.println("hap방법1=" + hap);
System.out.println("hap방법2=" + hap2);
}
}
|
cs |
28라인과 38라인을 처음에는
ArrayList kyo2 = new ArrayList();
kyo2 = list1;
위와 같은 식으로 구현했었다.
이렇게 하게 되면
1) ArrayList클래스의 인스턴스 kyo2가 메모리의 빈 공간에 생성된다. (ArrayList kyo2 = new ArrayList();)
2) 대입 연산자에 의해 list1의 주소값이 참조변수 kyo2에 저장된다. (kyo2 = list1;)
결국 두 참조변수가 참조하는 ArrayList가 동일해 지기 때문에 둘중 하나만 변경해도 다른쪽도 같이 변경된다.(두 참조변수가 참조하는 인스턴스는 동일함.)
수정한 코드는
ArrayList kyo2 = new ArrayList(list1);
kyo2.retainAll(list2);
이런식으로 하게 되면
ArrayList클래스의 인스턴스가 메모리의 빈 공간에 생성되고 그 내용은 list1의 값으로 초기화 하게 된다.(list1이 갖고있는 주소를 참조하여 그 인스턴스로 kyo2를 초기화)
그리고 나중엔 코드의 재사용성을 늘 고려하며 HashSet set = new HashSet(); 보다는
Set set = new HashSet(); 으로 해보는 것도 괜찮겠다.
<문제2>
[11-2] 다음 코드의 실행결과를 적으시오.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Exercise11_2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(3);
list.add(6);
list.add(2);
list.add(2);
list.add(2);
list.add(7);
HashSet set = new HashSet(list);
TreeSet tset = new TreeSet(set);
Stack stack = new Stack();
stack.addAll(tset);
while (!stack.empty())
System.out.println(stack.pop());
}
}
|
cs |
<나의 풀이>
List인터페이스를 구현한 ArrayList클래스는 List인터페이스의 '중복허용,순서유지'의 특성을 갖는다.
따라서 ArrayList list는 입력받은 그대로 3-6-2-2-2-7이 저장되게 된다.
이를 set인터페이스를 구현한 HashSet클래스로 변환해주면(컬렉션 클래스들은 서로 변환이 가능한 생성자를 가지고 있기 때문에 변환이 쉽다) set인터페이스의 특징(중복X,순서X)에 맞게 중복된 값이 삭제되고(3-6-2-7)
이를 다시 TreeSet으로 변환해주면 값을 입력받을때 자동으로 정렬해주는 TreeSet의 기능에 의해 2-3-6-7의 순서로 저장된다.
TreeSet의 값을 stack에 저장하고 스택은 LIFO(Last In First Out)의 방법으로 요소들을 꺼내게(pop)된다.
따라서 결과는 7-6-3-2
<문제3>
[11-5] 다음에 제시된 Student클래스가 Comparable인터페이스를 구현하도록 변경해서 이름(name)이 기본 정렬기준이 되도록 하시오.
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
|
class Student {
String name;
int ban;
int no;
int kor, eng, math;
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
int getTotal() {
return kor + eng + math;
}
float getAverage() {
return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
}
public String toString() {
return name + "," + ban + "," + no + "," + kor + "," + eng + "," + math + ","
+ getTotal() + "," + getAverage();
}
}
class Exercise11_5 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("홍길동", 1, 1, 100, 100, 100));
list.add(new Student("남궁성", 1, 2, 90, 70, 80));
list.add(new Student("김자바", 1, 3, 80, 80, 90));
list.add(new Student("이자바", 1, 4, 70, 90, 70));
list.add(new Student("안자바", 1, 5, 60, 100, 80));
Collections.sort(list);
Iterator it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
|
cs |
[실행결과]
김자바,1,3,80,80,90,250,83.3
남궁성,1,2,90,70,80,240,80.0
안자바,1,5,60,100,80,240,80.0
이자바,1,4,70,90,70,230,76.7
홍길동,1,1,100,100,100,300,100.0
<나의 풀이>
Comparable과 Comparator를 먼저 간단히 정리해보면 둘다 '비교기준'이라고 표현할 수 있겠다.
- Comparable : 기본 정렬기준을 구현하는데 사용.
- Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용.
간단히 말하자면 기본정렬(오름차순)이 필요할땐 Comparable, 그 외에 내림차순 등으로 정렬하고 싶으면 Comparator인터페이스의 내부 메서드를 오버라이딩 해주어 사용하면 된다.
같은 타입의 인스턴스끼리 서로 비교할 수 있는 클래스들은(wrapper클래스,String,Data 등) 기본적으로 오름차순으로 정렬될 수 있도록 내부적으로 Comparable인터페이스를 구현하고 있다. 이 말은 Comparable인터페이스를 구현한 클래스는 정렬이 가능하다는 것을 의미한다.(Comparable말 그대로 '비교할 수 있는')
Integer같은 wrapper클래스는 기본적으로 Comparable이 구현되어있지만 위 문제의 Student같은 사용자정의타입의 클래스의 객체들을 정렬가능하도록 만드려면 Comparable을 우리가 직접 구현해 주어야 한다.
1
2
3
4
5
6
7
8
9
10
|
public int compareTo(Object o) {
if (o instanceof Student) {
Student tmp = (Student) o;
return this.name.compareTo(tmp.name);
}
return -1;
}
|
cs |
Student 클래스에 Comparable인터페이스를 상속받고(class Student implements Comparable)
위와 같이 compareTo(Object o)를 오버라이딩 해주었다.
일단 인자값으로 들어오는 Object가 Student의 인스턴스인지 확인하고,( if(o instanceof Student)) true면 Object를 Studnet형으로 변환한다.( Student tmp = (Student) o; )
그리고 비교대상인 tmp의 name과 name인스턴스 변수와의 비교값을 return하는데
여기서 사용된 comparTo()는 name의 타입이 String이기 때문에 String클래스에 정의되어있는 compareTo(오름차순)를 이용하는 것이다.
<문제4>
[11-6] 다음의 코드는 성적평균의 범위별로 학생 수를 세기 위한 것이다. TreeSet이 학생들의 평균을 기준으로 정렬하도록 compare(Object o1, Object o2)와 평균점수의 범위를 주면 해당 범위에 속한 학생의 수를 반환하는 getGroupCount()를 완성하라.
[Hint] TreeSet의 subSet(Object from, Object to)를 사용하라.
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
|
import java.util.*;
class Student implements Comparable {
String name;
int ban;
int no;
int kor;
int eng;
int math;
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
int getTotal() {
return kor + eng + math;
}
float getAverage() {
return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
}
public String toString() {
return name + "," + ban + "," + no + "," + kor + "," + eng + "," + math + ","
+ getTotal() + "," + getAverage();
}
public int compareTo(Object o) {
if (o instanceof Student) {
Student tmp = (Student) o;
return name.compareTo(tmp.name);
} else {
return -1;
}
}
} // class Student
class Exercise11_6 {
static int getGroupCount(TreeSet tset, int from, int to) {
/*
* (1) 알맞은 코드를 넣어 완성하시오.
*/
}
public static void main(String[] args) {
TreeSet set = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
/*
* (2) 알맞은 코드를 넣어 완성하시오.
*/
}
});
set.add(new Student("홍길동", 1, 1, 100, 100, 100));
set.add(new Student("남궁성", 1, 2, 90, 70, 80));
set.add(new Student("김자바", 1, 3, 80, 80, 90));
set.add(new Student("이자바", 1, 4, 70, 90, 70));
set.add(new Student("안자바", 1, 5, 60, 100, 80));
Iterator it = set.iterator();
while (it.hasNext())
System.out.println(it.next());
System.out.println("[60~69] :" + getGroupCount(set, 60, 70));
System.out.println("[70~79] :" + getGroupCount(set, 70, 80));
System.out.println("[80~89] :" + getGroupCount(set, 80, 90));
System.out.println("[90~100] :" + getGroupCount(set, 90, 101));
}
}
|
cs |
[실행결과]
이자바,1,4,70,90,70,230,76.7
남궁성,1,2,90,70,80,240,80.0
김자바,1,3,80,80,90,250,83.3
홍길동,1,1,100,100,100,300,100.0
[60~69]:0
[70~79]:1
[80~89]:2
[90~100]:1
<나의 풀이>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
TreeSet set = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
Float s1Avr = s1.getAverage();
Float s2Avr = s2.getAverage();
if (s1Avr instanceof Comparable && s2Avr instanceof Comparable) {
Comparable c1 = (Comparable) s1Avr;
Comparable c2 = (Comparable) s2Avr;
return c1.compareTo(c2);
}
}
return -1;
}
});
|
cs |
Float클래스 내부의 compareTo를 이용한 방법이다. 딱 봐도 지저분해 보이고 Float클래스 내부의 compareTo도 결국 return값으로 값 비교를 할거라는 아이디어로 코드를 간단히 해봤다.
1
2
3
4
5
6
7
8
9
10
11
12
|
TreeSet set = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.getAverage()<s2.getAverage() ? -1 :
(s1.getAverage()==s2.getAverage() ? 0: 1);
}
return -1;
}
});
|
cs |
return값으로 삼항연산자를 이용하여 s1의 average와 s2의 average를 비교했다. compareTo의 반환값은 Int이지만 실제로는 비교하는 두 객체가 같으면 0, 비교하는 값보다 작으면 음수, 크면 양수를 반환하도록 구현해야 한다. average는 float형 이기 때문에 int형으로 캐스팅 하게 되면 정확도가 떨어질 수 있다. 따라서 조건문을 이용함.
1
2
3
4
5
6
7
8
|
static int getGroupCount(TreeSet tset, int from, int to) {
Student st = new Student("", 0, 0, from, from, from);
Student st2 = new Student("", 0, 0, to, to, to);
return tset.subSet(st, st2).size();
}
|
cs |
이건 도저히 어떻게 해야할까 감이 안잡혀서 해설을 보고 말았다.ㅜㅜ
처음 생각의 흐름은, tset의 Student요소들을 첫 index부터 마지막 index까지 average 인스턴스 변수를 from과 to로 비교하여 true면 getGroupCount내부에 정의한 count변수를 올려 마지막에 return하게끔 하려 했었다.
그러나 set은 index가 없고 (내가 모르는 것 일수 있겠으나)모든 요소들을 index형식으로 검색할 수 있는 방법이 없다!
Studnet st와 st2는 각 과목 점수를 모두 from과 to로 초기화 했다. st의 average는 결국 from이 될 것이고 st2는 to가 될 것이다.
subSet이라는 treeset의 메서드를 이용하면 범위검색(from~to~)이 가능한데, subSet을 호출하는건 tset이고 매개변수 tset에 들어가는 set의 정렬기준은 우리가 위에서 오버라이딩 했던 Compare의 기준에 따라(메서드 내부의 o1 instanceOf Student) set(=tset)의 'average'가 된다.
따라서 st1와 st2의 평균값 사이에 있는 요소들을 set형태로 return하고 그 size(갯수)를 최종적으로 return한다.
<문제5>
[11-7] 다음에 제시된 BanNoAscending클래스를 완성하여 ArrayList에 담긴 Student인스턴스들이 반(ban)과 번호(no) 로 오름차순 정렬되게 하시오.(반이 같은 경우 번호를 비교해서 정렬한다.)
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
|
import java.util.*;
class Student {
String name;
int ban;
int no;
int kor;
int eng;
int math;
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
int getTotal() {
return kor + eng + math;
}
float getAverage() {
return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
}
public String toString() {
return name + "," + ban + "," + no + "," + kor + "," + eng + ","
+ math + "," + getTotal() + "," + getAverage();
}
}// class Student
class BanNoAscending implements Comparator {
public int compare(Object o1, Object o2) {
/* 알맞은 코드를 넣어 완성하시오 (1) . */
}
}
class Exercise11_7 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("이자바", 2, 1, 70, 90, 70));
list.add(new Student("안자바", 2, 2, 60, 100, 80));
list.add(new Student("홍길동", 1, 3, 100, 100, 100));
list.add(new Student("남궁성", 1, 1, 90, 70, 80));
list.add(new Student("김자바", 1, 2, 80, 80, 90));
Collections.sort(list, new BanNoAscending());
Iterator it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
|
cs |
[실행결과]
남궁성,1,1,90,70,80,240,80.0
김자바,1,2,80,80,90,250,83.3
홍길동,1,3,100,100,100,300,100.0
이자바,2,1,70,90,70,230,76.7
안자바,2,2,60,100,80,240,80.0
<나의 풀이>
1
2
3
4
5
6
7
8
9
10
11
|
class BanNoAscending implements Comparator {
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.ban < s2.ban ? -1 : (s1.ban == s2.ban ? (s1.no < s2.no ? -1 : 1) : 1);
}
return -1;
}
}
|
cs |
삼항연산자가 세번이나 중첩됐고 ban이나 no가 int형이기 때문에 굳이 -1,1로 해줄 필요가 없었다.
compare의 return 값의 숫자를 보는것이 아니라 양/음수인지 0인지만 판단하여 정렬하기 때문에 두개를 비교하려면 그냥 빼주기만 하면 되기 때문이다.
뺄셈 결과가 -이면 앞이 작은수, +이면 앞이 큰수, 0이면 같은 수다.
따라서 아래와 같이 간략화 할 수 있다.
1
2
3
4
5
6
7
8
9
|
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
int result = s1.ban - s2.ban;
return result;
}
return -1;
}
|
cs |
<문제6>
[11-8] 문제11-7의 Student클래스에 총점(total)과 전교등수(schoolRank)를 저장하기 위한 인스턴스변수를 추가하였다. Student클래스의 기본정렬을 이름(name)이 아닌 총점(total)을 기준으로 한 내림차순으로 변경한 다음, 총점을 기준으로 각 학생의 전교등수를 계산하고 전교등수를 기준으로 오름차순 정렬하여 출력하시오.
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
|
import java.util.*;
class Student implements Comparable {
String name;
int ban;
int no;
int kor;
int eng;
int math;
int total; // 총점
int schoolRank; // 전교등수
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
total = kor + eng + math;
}
int getTotal() {
return total;
}
float getAverage() {
return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
}
public int compareTo(Object o) {
/*
* (1) 알맞은 코드를 넣어 완성하시오.
*/
}
public String toString() {
return name + "," + ban + "," + no + "," + kor + "," + eng + "," + math + "," + getTotal()
+ "," + getAverage() + "," + schoolRank; // 새로추가
}
}
class Exercise11_8 {
public static void calculateSchoolRank(List list) {
Collections.sort(list); // 먼저 list를 총점기준 내림차순으로 정렬한다.
int prevRank = -1; // 이전 전교등수
int prevTotal = -1; // 이전 총점
int length = list.size();
/*
* (2) 아래의 로직에 맞게 코드를 작성하시오.
* 1. 반복문을 이용해서 list에 저장된 Student객체를 하나씩 읽는다.
* 1.1 총점(total)이 이전총점(prevTotal)과 같으면 이전 등수(prevRank)를
* 등수(schoolRank)로 한다.
* 1.2 총점이 서로 다르면, 등수(schoolRank)의 값을 알맞게 계산해서 저장한다. * 이전에 동점자 였다면, 그 다음 등수는 동점자의 수를 고려해야한다. (실행결과 참고)
* 1.3 현재 총점과 등수를 이전총점(prevTotal)과 이전등수(prevRank)에 저장한다.
*/
}
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("이자바", 2, 1, 70, 90, 70));
list.add(new Student("안자바", 2, 2, 60, 100, 80));
list.add(new Student("홍길동", 1, 3, 100, 100, 100));
list.add(new Student("남궁성", 1, 1, 90, 70, 80));
list.add(new Student("김자바", 1, 2, 80, 80, 90));
calculateSchoolRank(list);
Iterator it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
|
cs |
[실행결과]
홍길동,1,3,100,100,100,300,100.0,1
김자바,1,2,80,80,90,250,83.3,2
안자바,2,2,60,100,80,240,80.0,3
남궁성,1,1,90,70,80,240,80.0,3
이자바,2,1,70,90,70,230,76.7,5
<나의 풀이>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public static void calculateSchoolRank(List list) {
Collections.sort(list); // 먼저 list를 총점기준 내림차순으로 정렬한다.
int prevRank = -1; // 이전 전교등수
int prevTotal = -1; // 이전 총점
int length = list.size();
for (int i = 0; i < length; i++) {
// 반복문을 이용해서 list에 저장된 Student객체를 하나씩 읽는다.
Student2 current = (Student2) list.get(i);
// 총점(total)이 이전총점(prevTotal)과 같으면 이전 등수(PrevRank)를 등수(schoolRank)로 한다.
if (current.total == prevTotal) {
current.schoolRank = prevRank;
} else {
// 총점이 이전총점과 같지 않으면 등수를 넣는다(i+1)
current.schoolRank = i + 1;
}
// 현재 schoolRank와 total을 prev변수들에 넣는다.
prevRank = current.schoolRank;
prevTotal = current.total;
}
|
cs |
<문제7>
[11-9] 문제11-8의 Student클래스에 반등수(classRank)를 저장하기 위한 인스턴스변수를 추가하였다. 반등수를 계산하고 반과 반등수로 오름차순 정렬하여 결과를 출력하시오. (1)~(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
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
|
import java.util.*;
class Student implements Comparable {
String name;
int ban;
int no;
int kor;
int eng;
int math;
int total;
int schoolRank; // 전교등수
int classRank; // 반등수
Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
total = kor + eng + math;
}
int getTotal() {
return total;
}
float getAverage() {
return (int) ((getTotal() / 3f) * 10 + 0.5) / 10f;
}
public int compareTo(Object o) {
if (o instanceof Student) {
Student tmp = (Student) o;
return tmp.total - this.total;
} else {
return -1;
}
}
public String toString() {
return name + "," + ban + "," + no + "," + kor + "," + eng + "," + math + "," + getTotal() + "," + getAverage()
+ "," + schoolRank + "," + classRank // 새로추가
;
}
} // class Student
class ClassTotalComparator implements Comparator {
public int compare(Object o1, Object o2) {
/*
* (1) 알맞은 코드를 넣어 완성하시오.
*/
}
}
class Exercise11_9 {
public static void calculateClassRank(List list) {
// 먼저 반별 총점기준 내림차순으로 정렬한다.
Collections.sort(list, new ClassTotalComparator());
int prevBan = -1;
int prevRank = -1;
int prevTotal = -1;
int length = list.size();
/*
* (2) 아래의 로직에 맞게 코드를 작성하시오. 1. 반복문을 이용해서 list에 저장된 Student객체를 하나씩 읽는다. 1.1 반이
* 달라지면,(ban과 prevBan이 다르면) 이전 등수(prevRank)와 이전 총점(prevTotal)을 초기화한다. 1.2
* 총점(total)이 이전총점(prevTotal)과 같으면 이전 등수(prevRank)를 등수(classRank)로 한다. 1.3 총점이
* 서로 다르면, 등수(classRank)의 값을 알맞게 계산해서 저장한다. 이전에 동점자였다면, 그 다음 등수는 동점자의 수를 고려해야
* 한다. (실행결과 참고) 1.4 현재 반과 총점과 등수를 이전 반(prevBan), 이전 총점(prevTotal), 이전
* 등수(prevRank)에 저장한다.
*/
} // public static void calculateClassRank(List list) {
public static void calculateSchoolRank(List list) {
/* 내용 생략 */
}
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("이자바", 2, 1, 70, 90, 70));
list.add(new Student("안자바", 2, 2, 60, 100, 80));
list.add(new Student("홍길동", 1, 3, 100, 100, 100));
list.add(new Student("남궁성", 1, 1, 90, 70, 80));
list.add(new Student("김자바", 1, 2, 80, 80, 90));
calculateSchoolRank(list);
calculateClassRank(list);
Iterator it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
|
cs |
[실행 결과]
홍길동,1,3,100,100,100,300,100.0,1,1
김자바,1,2,80,80,90,250,83.3,2,2
남궁성,1,1,90,70,80,240,80.0,3,3
안자바,2,2,60,100,80,240,80.0,3,1
이자바,2,1,70,90,70,230,76.7,5,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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
class ClassTotalComparator implements Comparator {
public int compare(Object o1, Object o2) {
if (o1 instanceof Student33 && o2 instanceof Student33) {
Student33 s1 = (Student33) o1;
Student33 s2 = (Student33) o2;
int tmp = s2.total - s1.total;
if (tmp == 0)
// 점수가 같을 경우 이름 오름차순 정렬.
return s1.name.compareTo(s2.name);
return tmp;
}
return -1;
}
}
class Exercise11_9 {
public static void calculateClassRank(List list) {
// 먼저 반별 총점기준 내림차순으로 정렬한다.
Collections.sort(list, new ClassTotalComparator());
int prevBan = -1;
int prevRank = -1;
int prevTotal = -1;
int length = list.size();
for (int i = 0; i < length; i++) {
Student33 tmp = (Student33) list.get(i);
// 반이 이전반과 같지 않으면 새로 count시작해야하니 초기화.
if (tmp.ban != prevBan) {
prevRank = 0;
prevTotal = 0;
}
// 이전 점수와 현재 점수가 같으면 이전점수와 같은 rank를 주고
// 그 다음 등수를 고려하여 이전 점수를 1 올려준다.
if (tmp.total == prevTotal) {
tmp.classRank = prevRank;
prevRank++;
} else {
// 이전 점수와 현재 점수가 같지 않으면 이전점수 +1을 rank로 주고
// prevRank를 현재점수로 초기화한다.
tmp.classRank = prevRank + 1;
prevRank = tmp.classRank;
}
// 다음 계산이 가능하도록 현재 ban,total을 각각 이전ban, total에 초기화.
prevBan = tmp.ban;
prevTotal = tmp.total;
}
} // public static void calculateClassRank(List list)
|
cs |
'Tech > Java' 카테고리의 다른 글
[Java] 날짜와 시간 & 형식화(date, time and formatting) (0) | 2019.08.29 |
---|---|
[Java] AWT를 이용한 GUI빙고게임 (0) | 2019.08.27 |
[Java] 컬렉션 프레임워크(Collections Framework) (0) | 2019.08.22 |
[Java] Vector 구현 (0) | 2019.08.21 |
[Java] Object-Oriented Programming (0) | 2019.08.08 |
댓글