안녕하세요.

이번에는 오랫만에 삽질한(맨날 삽질하면서 무슨...) 정렬에 대해서 포스팅을 해보려고 합니다.

 

기본적인건데 맨날 삽질하는 것도 있고, 까먹는 것도 있고 해서 겸사겸사 기록용으로 올릴겸 포스팅을 해봅니다.

 

이번 포스팅에서 다룰 주제는 다음과 같습니다.

 

1. List<String> 과 같은 일반적인 부분이 아닌 List<ClassName> ex) List<TestDate> 형식의 객체를 요소로 가지고 있는 List의 정렬에 대하여 알아보겠습니다.

2. Date 타입의 필드를 기준으로 정렬하는 방법에 대하여 알아보도록 하겠습니다.

3. Collections / Comparator / Collectors 로 정렬 하는 방법에 대하여 알아보도록 하겠습니다.

 

* 위에서 말씀드렸지만 이번에 다루게 될 정렬 Data의 타입은 Date 타입입니다.

  솔직히 Date 타입은 어떻게 정렬해야되나 생각하면서 Date -> String 으로 바꿔보기도하고 별짓을 다했었는데

  의미가 없더라구요. (그건 제가 못해서...)

 

우선 테스트를 위한 TestDate 클래스를 작성하도록 하겠습니다.

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
import java.util.Date;
 
public class TestDate {
    private String userId;
    private String userName;
    private Date register_dt;
    private String tmpField1;
    
    public TestDate(String userId, String userName) {
        this.userId = userId;
        this.userName = userName;
    }
    
    public String getUserId() {
        return this.userId;
    }
    
    public String getUserName() {
        return this.userName;
    }
    
    public Date getRegister_Dt() {
        return this.register_dt;
    }
    
    public String getTmpField1() {
        return this.tmpField1;
    }
    
    public void setUserId(String userId) {
        this.userId = userId;
    }
    
    public void setUsername(String userName) {
        this.userName = userName;
    }
    
    public void setRegister_Dt(Date register_dt) {
        this.register_dt = register_dt;
    }
    
    public void setTmpField1(String tmpField1) {
        this.tmpField1 = tmpField1;
    }
}
cs

 

 

작성한 TestDate 클래스를 활용하여 정렬을 해보겠습니다.

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.Comparator;
import java.util.Arrays;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
 
public class DateTestMain {
    public static void main(String[] args) {
        // 테스트를 위한 초기값 설정
        DateFormat df = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSSS");
        
        TestDate td1 = new TestDate("td1""td1");
        TestDate td2 = new TestDate("td2""td2");
        TestDate td3 = new TestDate("td3""td3");
        TestDate td4 = new TestDate("td4""td4");
        TestDate td5 = new TestDate("td5""td5");
        TestDate td6 = new TestDate("td6""td6");
        TestDate td7 = new TestDate("td7""td7");
        TestDate td8 = new TestDate("td8""td8");
        TestDate td9 = new TestDate("td9""td9");
        TestDate td10 = new TestDate("td10""td10");
 
        // Date 값의 비교를 위해 for문을 100만 번 씩 반복 하였습니다.
        if(td1.getRegister_Dt()==null)    td1.setRegister_Dt(new Date());
        if(td1.getTmpField1()==null || "".equals(td1.getTmpField1())) td1.setTmpField1("080");
        for(int i=0; i<1000000; i++) {}
        if(td2.getRegister_Dt()==null)    td2.setRegister_Dt(new Date());
        if(td2.getTmpField1()==null || "".equals(td2.getTmpField1())) td2.setTmpField1("075");
        for(int i=0; i<1000000; i++) {}
        if(td3.getRegister_Dt()==null)    td3.setRegister_Dt(new Date());
        if(td3.getTmpField1()==null || "".equals(td3.getTmpField1())) td3.setTmpField1("070");
        for(int i=0; i<1000000; i++) {}
        if(td4.getRegister_Dt()==null)    td4.setRegister_Dt(new Date());
        if(td4.getTmpField1()==null || "".equals(td4.getTmpField1())) td4.setTmpField1("100");
        for(int i=0; i<1000000; i++) {}
        if(td5.getRegister_Dt()==null)    td5.setRegister_Dt(new Date());
        if(td5.getTmpField1()==null || "".equals(td5.getTmpField1())) td5.setTmpField1("005");
        for(int i=0; i<1000000; i++) {}
        if(td6.getRegister_Dt()==null)    td6.setRegister_Dt(new Date());
        if(td6.getTmpField1()==null || "".equals(td6.getTmpField1())) td6.setTmpField1("010");
        for(int i=0; i<1000000; i++) {}
        if(td7.getRegister_Dt()==null)    td7.setRegister_Dt(new Date());
        if(td7.getTmpField1()==null || "".equals(td7.getTmpField1())) td7.setTmpField1("020");
        for(int i=0; i<1000000; i++) {}
        if(td8.getRegister_Dt()==null)    td8.setRegister_Dt(new Date());
        if(td8.getTmpField1()==null || "".equals(td8.getTmpField1())) td8.setTmpField1("100");
        for(int i=0; i<1000000; i++) {}
        if(td9.getRegister_Dt()==null)    td9.setRegister_Dt(new Date());
        if(td9.getTmpField1()==null || "".equals(td9.getTmpField1())) td9.setTmpField1("005");
        for(int i=0; i<1000000; i++) {}
        if(td10.getRegister_Dt()==null)    td10.setRegister_Dt(new Date());
        if(td10.getTmpField1()==null || "".equals(td10.getTmpField1())) td10.setTmpField1("010");
 
        List<TestDate> tdList = Arrays.asList(td2, td1, td3, td10, td5, td8, td9, td4, td6, td7); // 테스트용 List
 
        for(TestDate td : tdList) // List에 값이 어떤식으로 저장되어 있는지 확인 하기 위해 출력
            System.out.println("userName : " + td.getUserName() + " / reg_dt : " + df.format(td.getRegister_Dt()));
 
        // 출력 결과
        /*
         * userName : td2 / reg_dt : 2020.08.25 09:08:35.0816 
         * userName : td1 / reg_dt : 2020.08.25 09:08:35.0809
         * userName : td3 / reg_dt : 2020.08.25 09:08:35.0818
         * userName : td10 / reg_dt : 2020.08.25 09:08:35.0830
         * userName : td5 / reg_dt : 2020.08.25 09:08:35.0821
         * userName : td8 / reg_dt : 2020.08.25 09:08:35.0826
         * userName : td9 / reg_dt : 2020.08.25 09:08:35.0828
         * userName : td4 / reg_dt : 2020.08.25 09:08:35.0820
         * userName : td6 / reg_dt : 2020.08.25 09:08:35.0823
         * userName : td7 / reg_dt : 2020.08.25 09:08:35.0825
         */
 
        //=============== 정렬 시작 ===============
        /*
         * Option 1
         * Collections.sort() with Comparator
         */
        Collections.sort(tdList, new Comparator<TestDate>() { // 익명객체 사용
            @Override
            public int compare(TestDate arg1, TestDate arg2) { // Sort Order By asc
                return arg1.getRegister_Dt().compareTo(arg2.getRegister_Dt()); // arg1 - 기준 값, arg2 - 비교 값
            }
        });
 
        Collections.sort(tdList, new Comparator<TestDate>() { // 익명객체 사용
            @Override
            public int compare(TestDate arg1, TestDate arg2) { // Sort Order By desc
                return arg2.getRegister_Dt().compareTo(arg1.getRegister_Dt()); // arg2 - 기준 값, arg1 - 비교 값
            }
        });
 
        /*
         * Option 2
         * List interface sort() [Java 8]
         */
        tdList.sort(Comparator.comparing(TestDate::getRegister_Dt)); // Sort Order By asc - Comparator의 comparing 사용, ::를 활용한 참조 방식 사용
        tdList.sort(Comparator.comparing(TestDate::getRegister_Dt).reversed()); // Sort Order By desc - Comparator의 comparing 사용, ::를 활용한 참조 방식 사용, reversed 사용시 내림차순
 
        /*
         * Option 3
         * Stream interface sorted() [Java 8]
         */
        List<TestDate> ascTD = tdList.stream() // Sort Order By asc - Comparator의 comparing 사용, ::를 활용한 참조 방식 사용, stream을 활용한 List의 sorted사용 및 collect를 활용한 Collectors.toList() 사용
                .sorted(Comparator.comparing(TestDate::getRegister_Dt))
                .collect(Collectors.toList());
 
        List<TestDate> descTD = tdList.stream() // Sort Order By desc - Comparator의 comparing 사용, ::를 활용한 참조 방식 사용, stream을 활용한 List의 sorted사용 및 collect를 활용한 Collectors.toList() 사용, reversed 사용시 내림차순
                .sorted(Comparator.comparing(TestDate::getRegister_Dt).reversed())
                .collect(Collectors.toList());
 
        //=============== 정렬 종료 ===============
 
        /*
         * 위 Option 1~3 까지의 방식 중 하나를 사용하셔서 정렬을 하신 후 출력을 해보시면 다음과 같은 결과를 확인하실 수 있습니다.
         * 여기서는 desc (내림차순) 방식으로 정렬 및 테스트를 진행 하였습니다.
         */
 
        for(TestDate td : tdList)
            System.out.println("userName : " + td.getUserName() + " / reg_dt : " + df.format(td.getRegister_Dt()));
 
        // 출력 결과
        /*
         * userName : td10 / reg_dt : 2020.08.25 09:08:35.0830
         * userName : td9 / reg_dt : 2020.08.25 09:08:35.0828
         * userName : td8 / reg_dt : 2020.08.25 09:08:35.0826
         * userName : td7 / reg_dt : 2020.08.25 09:08:35.0825
         * userName : td6 / reg_dt : 2020.08.25 09:08:35.0823
         * userName : td5 / reg_dt : 2020.08.25 09:08:35.0821
         * userName : td4 / reg_dt : 2020.08.25 09:08:35.0820
         * userName : td3 / reg_dt : 2020.08.25 09:08:35.0818
         * userName : td2 / reg_dt : 2020.08.25 09:08:35.0816
         * userName : td1 / reg_dt : 2020.08.25 09:08:35.0809
         */
 
        // 추가로 날짜 정렬 이후, 우선 순위에 따라 정렬을 해보고 결과를 확인해 보겠습니다. (desc-내림차순 정렬 사용)
 
        tdList.sort(Comparator.comparing(TestDate::getTmpField1).reversed()); // 소스코드가 짧아서 이렇게 썼습니다. (사실은 귀찮아서...)
 
        for(TestDate td : tdList)
            System.out.println("userName : " + td.getUserName() + " / tmpField : " + td.getTmpField1());
 
        // 출력 결과
        /*
         * userName : td8 / tmpField : 100
         * userName : td4 / tmpField : 100
         * userName : td1 / tmpField : 080
         * userName : td2 / tmpField : 075
         * userName : td3 / tmpField : 070
         * userName : td7 / tmpField : 020
         * userName : td10 / tmpField : 010
         * userName : td6 / tmpField : 010
         * userName : td9 / tmpField : 005
         * userName : td5 / tmpField : 005
         */
    }
}
cs

 

결론부터 말씀드리면

 

포스팅의 목적이었던

 

- Date 타입의 필드만으로 정렬하기

- Date 타입으로 정렬 후, 우선 순위에 따라 정렬하기

 

위 2가지가 정상적으로 작동하는 것을 확인 하실 수 있습니다.

 

1. compare 오버라이딩

2. compareTo로 비교

3. Date 타입 -> String 타입 x / Date 타입 자체만으로 compareTo로 비교

4. 3까지의 과정 이후 우선순위에 따라 정렬하기

 

이렇게 하면 원하는 방식으로 정렬을 하실 수 있습니다.

 

위의 정렬 소스코드에서 Option 1을 제외한 Option 2, 3의 경우 Java 8 이라고 명시해 놓았는데,

Java 8 버전 이후부터 Option 2, 3 방식이 지원되기에 가능한 방식어서 명시해 놓았습니다.

* Option 2의 List.sort()는 Java 8 버전이 아니어도 지원이 됩니다.

  :: 참조 방식에 대한 지원이 Java 8 버전 이후부터 지원이 되므로 주의 하시기 바랍니다.

 

여기서는 소스코드에 대해서 자세하게 설명하지 않겠습니다.

 

핵심인 Date 타입 자체만으로도 비교가 가능하다는 것을 알고, 정렬 방식의 종류버전에 따른 차이가 있다는 점을 마지막으로 포스팅을 마치도록 하겠습니다.

 

 

+ Recent posts