item 14 junghyunlyoo - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
* <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
* -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>x.compareTo(y)</tt> must throw an exception iff
* <tt>y.compareTo(x)</tt> throws an exception.)
*
* <p>The implementor must also ensure that the relation is transitive:
* <tt>(x.compareTo(y)>0 && y.compareTo(z)>0)</tt> implies
* <tt>x.compareTo(z)>0</tt>.
*
* <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
* implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
* all <tt>z</tt>.
*
* <p>It is strongly recommended, but <i>not</i> strictly required that
* <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>. Generally speaking, any
* class that implements the <tt>Comparable</tt> interface and violates
* this condition should clearly indicate this fact. The recommended
* language is "Note: this class has a natural ordering that is
* inconsistent with equals."
*
* <p>In the foregoing description, the notation
* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
* <tt>0</tt>, or <tt>1</tt> according to whether the value of
* <i>expression</i> is negative, zero or positive.
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
๊ฐ์ฒด๊ฐ์ ๋น๊ต๋ฅผ ์ฉ์ดํ๊ฒ ํด์ฃผ๋ ์ธํฐํ์ด์ค์ด๋ค.
์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ค์ ์๋ก๊ฐ์ ๋น๊ต ์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ค.
(์๋์ ๋ฑ์ฅํ๋ ๊ตฌํ ๊ท์ฝ์ ์งํจ๋ค๋ ์ ์ ํ์)
๋ํ ์ด๋ฌํ ๊ฐ์ฒด๋ค์ ์์ฐ์ ์ธ ์์(natural order)๊ฐ ์์์ ๋ปํ๊ฒ ๋๋ค.
์ด๋ฌํ ํน์ง ๋๋ถ์ ๋น๊ต ์ฐ์ฐ์ด ํฌํจ๋ ์ฌ๋ฌ ์๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์
์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ค์๊ฒ Arrays.sort์ด๋ Collections.addAll ๋ฑ์ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํ๋ค.
์ฌ์ค์ ์๋ฐ ํ๋ซํผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ๋ ๊ฐ ํด๋์ค์ ์ด๊ฑฐ ํ์ (item 34)์ด Comparable์ ๊ตฌํํ๋ค.
์ํ๋ฒณ, ์ซ์, ์ฐ๋ ๊ฐ์ด ์์๊ฐ ๋ช ํํ ๊ฐ ํด๋์ค๋ฅผ ์ ์ํ๋ค๋ฉด ๋ฐ๋์ Comparable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์.
compareTo ๋ฉ์๋๋ฅผ ์์ฑํ ๋์๋ ๋ช ๊ฐ์ง ์ง์ผ์ผ ํ๋ ๊ท์ฝ์ด ์๋ค.
1. ๋งค๊ฐ๋ณ์ ์ธ์คํด์ค์ ์์ ์ ์ธ์คํด์ค๋ฅผ ๋น๊ตํ๋๋ก ํด์ผ ํ๋ค.
์์ ์ ์ธ์คํด์ค๊ฐ ๋งค๊ฐ๋ณ์ ์ธ์คํด์ค๋ณด๋ค ์์ผ๋ฉด ์์ ์ ์๋ฅผ, ๊ฐ์ผ๋ฉด 0์, ํฌ๋ฉด ์์ ์ ์๋ฅผ ๋ฐํํ๋ค.
์์ ์ ์ธ์คํด์ค์ ๋น๊ตํ ์ ์๋ ํ์
์ ์ธ์คํด์ค๊ฐ ์ฃผ์ด์ง๋ฉด ClassCastException์ ๋์ง๋ค.
2. ๋ชจ๋ x,y์ ๋ํด sgn(x.compareTo(y)) == -sgn(y.compareTo(x))์ฌ์ผ ํ๋ค.
* sgn => ํํ์์ ๊ฐ์ด ์์, 0, ์์์ผ ๋ ๊ฐ๊ฐ -1, 0, 1์ ๋ฐํํ๋ ํจ์
3. x.compareTo(y) > 0 && y.compareTo(z) > 0 ์ด๋ฉด x.compareTo(z) > 0์ด๋ค. ์ฆ, ์ถ์ด์ฑ์ ๋ณด์ฅํด์ผ ํ๋ค.
4. x.compareTo(y) == 0 ์ด๋ฉด ๋ชจ๋ z์ ๋ํด sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ์ด๋ค.
5. (x.compareTo(y) == 0) == (x.equals(y))์ฌ์ผ ํ๋ค. ์ด ๊ท์ฝ์ ์งํค์ง ์๋ ๋ชจ๋ ํด๋์ค๋ ๊ทธ ์ฌ์ค์ ๋ช
์ํด์ผ ํ๋ค.
์) "์ฃผ์: ์ด ํด๋์ค์ ์์๋ equals ๋ฉ์๋์ ์ผ๊ด๋์ง ์๋ค."
๋ชจ๋ ๊ฐ์ฒด์ ๋ํด ์ ์ญ ๋์น๊ด๊ณ๋ฅผ ๋ถ์ฌํ๋ equals ๋ฉ์๋์ ๋ฌ๋ฆฌ,
(๋ชจ๋ ์ผ์ด์ค์ ๋ํด true or false๋ฅผ return ํด์ผ ํ๋ค๋ ์๋ฏธ๋ก ํด์๋๋ค.)
compareTo๋ ํ์ ์ด ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ ๊ฒฝ ์ฐ์ง ์์๋ ๋๋ค.
ํ์ ์ด ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ฃผ์ด์ง๋ฉด ๊ฐ๋จํ ClassCastException์ ๋์ ธ๋ ๋๋ค.
๋ฌผ๋ก ๋ค๋ฅธ ํ์ ์ฌ์ด์ ๋น๊ต๋ ํ์ฉํ๋๋ฐ ๋ณดํต์ ๋น๊ตํ ๊ฐ์ฒด๋ค์ด ๊ตฌํํ ๊ณตํต ์ธํฐํ์ด์ค๋ฅผ ๋งค๊ฐ๋ก ์ด๋ค์ง๋ค.
hashCode ๊ท์ฝ์ ์งํค์ง ๋ชปํ๋ฉด ํด์๋ฅผ ์ฌ์ฉํ๋ ํด๋์ค์ ์ด์ธ๋ฆฌ์ง ๋ชปํ๊ฒ ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก compareTo ๊ท์ฝ์ ์งํค์ง ๋ชปํ๋ฉด ๋น๊ต๋ฅผ ํ์ฉํ๋ ํด๋์ค์ ์ด์ธ๋ฆฌ์ง ๋ชปํ๋ค.
๋น๊ต๋ฅผ ํ์ฉํ๋ ํด๋์ค์ ์๋ก๋ ์ ๋ ฌ๋ ์ปฌ๋ ์ ์ธ TreeSet๊ณผ TreeMap์ด ์๊ณ ๊ฒ์๊ณผ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ๋
์ ํธ๋ฆฌํฐ ํด๋์ค์ธ Collections์ Arrays๊ฐ ์๋ค.
์์ compareTo ๋ง์ง๋ง ๊ท์ฝ์ ํ์๋ ์๋์ง๋ง ๊ผญ ์งํค๊ธธ ๊ถํ๋ค.
๋ง์ง๋ง ๊ท์ฝ์ ๊ฐ๋จํ ๋งํ๋ฉด compareTo ๋ฉ์๋๋ก ์ํํ ๋์น์ฑ ํ ์คํธ์ ๊ฒฐ๊ณผ๊ฐ equals์ ๊ฒฐ๊ณผ์ ๊ฐ์์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ์ ์งํค๋ฉด compareTo๋ก ์ค์ง์ ์์์ equals์ ๊ฒฐ๊ณผ๊ฐ ์ผ๊ด๋๊ฒ ๋๋ค.
compareTo์ ์์์ equals์ ๊ฒฐ๊ณผ๊ฐ ์ผ๊ด๋์ง ์์ ํด๋์ค๋ ๋์์ ํ๋ค.
ํ์ง๋ง ์ด ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ์ ๋ ฌ๋ ์ปฌ๋ ์ ์ ๋ฃ์ผ๋ฉด, ํด๋น ์ปฌ๋ ์ ์ด ๊ตฌํํ ์ธํฐํ์ด์ค(Collection, Set, Map)์ ์ ์๋ ๋์๊ณผ ์๋ฐ์๋ฅผ ๋ผ ๊ฒ์ด๋ค.
์ด ์ธํฐํ์ด์ค๋ค์ equals ๋ฉ์๋์ ๊ท์ฝ์ ๋ฐ๋ฅธ๋ค๊ณ ๋์ด ์์ง๋ง ๋๋๊ฒ๋ ์ ๋ ฌ๋ ์ปฌ๋ ์ ๋ค์ ๋์น์ฑ์ ๋น๊ตํ ๋ equals ๋์ compareTo๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
compareTo์ equals๊ฐ ์ผ๊ด๋์ง ์๋ BigDecimal ํด๋์ค๋ฅผ ์๋ก ์๊ฐํด๋ณด์.
๋น HashSet ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ค์ new BigDecimal("1.0")๊ณผ new BigDecimal("1.00")์ ์ฐจ๋ก๋ก ์ถ๊ฐํ๋ค.
์ด ๋ BigDecimal์ equals ๋ฉ์๋๋ก ๋น๊ตํ๋ฉด ์๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ HashSet์ ์์๋ฅผ 2๊ฐ ๊ฐ๊ฒ ๋๋ค.
ํ์ง๋ง HashSet ๋์ TreeSet์ ์ฌ์ฉํ๋ฉด ์์๋ฅผ ํ๋๋ง ๊ฐ๊ฒ ๋๋ค.
compareTo ๋ฉ์๋๋ก ๋น๊ตํ๋ฉด ๋ BigDecimal ์ธ์คํด์ค๊ฐ ๋๊ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflated().equals(xDec.inflated());
}
public int compareTo(BigDecimal val) {
// Quick path for equal scale and non-inflated case.
if (scale == val.scale) {
long xs = intCompact;
long ys = val.intCompact;
if (xs != INFLATED && ys != INFLATED)
return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
}
int xsign = this.signum();
int ysign = val.signum();
if (xsign != ysign)
return (xsign > ysign) ? 1 : -1;
if (xsign == 0)
return 0;
int cmp = compareMagnitude(val);
return (xsign > 0) ? cmp : -cmp;
}
๊ธฐ์กด ํด๋์ค๋ฅผ ํ์ฅํ ๊ตฌ์ฒด ํด๋์ค์์ ์๋ก์ด ๊ฐ ์ปดํฌ๋ํธ(ํ๋)๋ฅผ ์ถ๊ฐํ๋ค๋ฉด
compareTo ๊ท์ฝ์ ์งํฌ ๋ฐฉ๋ฒ์ด ์๋ค. (item 10)
(๊ฐ์ฒด ์งํฅ์ ์ถ์ํ์ ์ด์ ์ ํฌ๊ธฐํ๋ค๋ฉด ๊ฐ๋ฅํ ์๋ ์๋ค.)
์ด ์ฃผ์์ฌํญ์ equals์๋ ์ ์ฉ๋๋ค. ์ฐํ๋ฒ์ ์ญ์ equals์์์ ์ฐํ๋ฒ๊ณผ ๊ฐ๋ค.
Comparable์ ๊ตฌํํ ํด๋์ค๋ฅผ ํ์ฅํด ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด, ํ์ฅํ๋ ๋์ ๋
๋ฆฝ๋ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ , ์ด ํด๋์ค์ ์๋ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ํ๋๋ฅผ ๋์.
๊ทธ๋ฐ ๋ค์ ๋ด๋ถ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ '๋ทฐ' ๋ฉ์๋๋ฅผ ์ ๊ณตํ์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐ๊นฅ ํด๋์ค์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ compareTo ๋ฉ์๋๋ฅผ ๊ตฌํํด ๋ฃ์ ์ ์๋ค.
ํด๋ผ์ด์ธํธ๋ ํ์์ ๋ฐ๋ผ ๋ฐ๊นฅ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ํ๋ ์์ ๋ด๊ธด ์๋ ํด๋์ค์ ์ธ์คํด์ค๋ก ๋ค๋ฃฐ ์๋ ์์ ๊ฒ์ด๋ค.
Compareble์ ํ์
์ ์ธ์๋ก ๋ฐ๋ ์ ๋ค๋ฆญ ์ธํฐํ์ด์ค์ด๋ฏ๋ก compareTo ๋ฉ์๋์ ์ธ์ ํ์
์ ์ปดํ์ผํ์์ ์ ํด์ง๋ค.
์
๋ ฅ ์ธ์์ ํ์
์ ํ์ธํ๊ฑฐ๋ ํ๋ณํํ ํ์๊ฐ ์๋ค๋ ๋ป์ด๋ค.
์ธ์์ ํ์
์ด ์๋ชป๋๋ค๋ฉด ์ปดํ์ผ ์์ฒด๊ฐ ๋์ง ์๋๋ค.
๋ํ null์ ์ธ์๋ก ๋ฃ์ด ํธ์ถํ๋ฉด NullPointerException์ ๋์ ธ์ผ ํ๋ค.
๋ฌผ๋ก ์ค์ ๋ก๋ ์ธ์(์ด ๊ฒฝ์ฐ null)์ ๋ฉค๋ฒ์ ์ ๊ทผํ๋ ค๋ ์๊ฐ ์ด ์์ธ๊ฐ ๋์ ธ์ง ๊ฒ์ด๋ค.
(์ ๊ท์ฝ๋๋ก ๊ตฌํ๋) compareTo๋ ๊ฐ ํ๋๊ฐ ๋์น์ธ์ง๋ฅผ ๋น๊ตํ๋ ๊ฒ ์๋๋ผ ๊ทธ ์์๋ฅผ ๋น๊ตํ๋ค.
๊ฐ์ฒด ์ฐธ์กฐ ํ๋๋ฅผ ๋น๊ตํ๋ ค๋ฉด compareTo ๋ฉ์๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ๋ค.
Comparable์ ๊ตฌํํ์ง ์์ ํ๋๋ ํ์ค์ด ์๋ ์์๋ก ๋น๊ตํด์ผ ํ๋ค๋ฉด ๋น๊ต์(Comparator)๋ฅผ ๋์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋น๊ต์๋ ์ง์ ๋ง๋ค๊ฑฐ๋ ์๋ฐ๊ฐ ์ ๊ณตํ๋ ๊ฒ ์ค์ ๊ณจ๋ผ ์ฐ๋ฉด ๋๋ค.
์๋ ์ฝ๋๋ item 10 ์์ ๊ตฌํํ CaseInsensitiveString์ compareTo ๋ฉ์๋๋ก, ์๋ฐ๊ฐ ์ ๊ณตํ๋ ๋น๊ต์๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
package effectivejava.chapter3.item14;
import java.util.*;
public final class CaseInsensitiveString
implements Comparable<CaseInsensitiveString> {
public int compareTo(CaseInsensitiveString cis) {
return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s);
}
}
CaseInsensitiveString์ด Comparable์ ๊ตฌํํ ๊ฒ์ ๋ณด์. CaseInsensitiveString์ ์ฐธ์กฐ๋ CaseInsensitiveString ์ฐธ์กฐ์๋ง ๋น๊ตํ ์ ์๋ค๋ ์๋ฏธ์ด๋ค. ์ด๋ Comparable์ ๊ตฌํํ ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฐ๋ฅด๋ ํจํด์ด๋ค.
์ด ์ฑ ์ 2ํ์์๋ compareTo ๋ฉ์๋์์ ์ ์ ๊ธฐ๋ณธ ํ์ ํ๋๋ฅผ ๋น๊ตํ ๋๋ ๊ด๊ณ ์ฐ์ฐ์ <์ >๋ฅผ, ์ค์ ๊ธฐ๋ณธ ํ์ ํ๋๋ฅผ ๋น๊ตํ ๋๋ ์ ์ ๋ฉ์๋์ธ Double.compare์ Float.compare๋ฅผ ์ฌ์ฉํ๋ผ๊ณ ๊ถํ๋ค.
๊ทธ๋ฐ๋ฐ java 7 ๋ถํฐ๋ ์ํฉ์ด ๋ณํ๋ค.
๋ฐ์ฑ๋ ๊ธฐ๋ณธ ํ์ ํด๋์ค๋ค์ ์๋ก ์ถ๊ฐ๋ ์ ์ ๋ฉ์๋์ธ compare๋ฅผ ์ด์ฉํ๋ฉด ๋๋ค.
compareTo ๋ฉ์๋์์ ๊ด๊ณ์ฐ์ฐ์ <์ >๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์ค๋ฅ๋ฅผ ์ ๋ฐํ ์ ์์ผ๋์ด์ ๋ ์ถ์ฒํ์ง ์๋๋ค.
public final class Integer extends Number
implements Comparable<Integer>, Constable, ConstantDesc {
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
ํด๋์ค์ ํต์ฌ ํ๋๊ฐ ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด ์ด๋ ๊ฒ์ ๋จผ์ ๋น๊ตํ๋๋๊ฐ ์ค์ํด์ง๋ค.
๊ฐ์ฅ ํต์ฌ์ ์ธ ํ๋๋ถํฐ ๋น๊ตํ์. ๊ฐ์ฅ ํต์ฌ์ด ๋๋ ํ๋๊ฐ ๋๊ฐ๋ค๋ฉด ๋๊ฐ์ง ์์ ํ๋๋ฅผ ์ฐพ์ ๋๊น์ง ๊ทธ ๋ค์์ผ๋ก ์ค์ํ ํ๋๋ฅผ ๋น๊ตํ์.
์๋๋ item 10์ PhoneNumber ํด๋์ค์ compareTo ๋ฉ์๋์ ์ ๋ฐฉ๋ฒ์ ์ ์ฉํ ์ฝ๋๋ค.
public int compareTo(PhoneNumber pn) {
int result = Short.compare(areaCode, pn.areaCode);
if (result == 0) {
result = Short.compare(prefix, pn.prefix);
if (result == 0)
result = Short.compare(lineNum, pn.lineNum);
}
return result;
}
java 8์์๋ Comparator ์ธํฐํ์ด์ค๊ฐ ๋น๊ต์ ์์ฑ ๋ฉ์๋์ ํจ๊ป ์ฐ์ ๋ฐฉ์์ผ๋ก ๋น๊ต์๋ฅผ ์์ฑํ ์ ์๊ฒ ๋์๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋น๊ต์๋ค์ Comparable ์ธํฐํ์ด์ค๊ฐ ์ํ๋ compareTo ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ ๋ฐ ํ์ฉํ ์ ์๋ค.
(ํ์ง๋ง ์ฝ๊ฐ์ ์ฑ๋ฅ์ด ๋๋ ค์ง ์ ์๋ค๊ณ ํ๋ค.)
์๋๋ PhoneNumber ํด๋์ค์ compareTo ๋ฉ์๋์ ์ฐ์ ๋ฐฉ์์ ์ ์ฉํ ์ฝ๋๋ค.
private static final Comparator<PhoneNumber> COMPARATOR =
comparingInt((PhoneNumber pn) -> pn.areaCode)
.thenComparingInt(pn -> pn.prefix)
.thenComparingInt(pn -> pn.lineNum);
public int compareTo(PhoneNumber pn) {
return COMPARATOR.compare(this, pn);
}
์ด ์ฝ๋๋ ํด๋์ค๋ฅผ ์ด๊ธฐํํ ๋ ๋น๊ต์ ์์ฑ ๋ฉ์๋ 2๊ฐ๋ฅผ ์ด์ฉํด ๋น๊ต์๋ฅผ ์์ฑํ๋ค.
๊ทธ ์ค ์ฒซ ๋ฒ์งธ์ธ comparingInt๋ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ int ํ์ ํค์ ๋งคํํ๋ ํค ์ถ์ถ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์, ๊ทธ ํค๋ฅผ ๊ธฐ์ค์ผ๋ก ์์๋ฅผ ์ ํ๋ ๋น๊ต์๋ฅผ ๋ฐํํ๋ ์ ์ ๋ฉ์๋๋ค.
์์ ์์์ comparingInt๋ ๋๋ค๋ฅผ ์ธ์๋ก ๋ฐ์ผ๋ฉฐ, ์ด ๋๋ค๋ PhoneNumber์์ ์ถ์ถํ ์ง์ญ ์ฝ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ํ๋ฒํธ์ ์์๋ฅผ ์ ํ๋ Comparator๋ฅผ ๋ฐํํ๋ค.
์ด ๋๋ค์์ ์ ๋ ฅ ์ธ์์ ํ์ (PhoneNumber pn)์ ๋ช ์ํ ์ ์ ์ฃผ๋ชฉํ์.
์๋ฐ์ ํ์ ์ถ๋ก ๋ฅ๋ ฅ์ด ์ด ์ํฉ์์๋ ํ์ ์ ์์๋ผ ๋งํผ ๊ฐ๋ ฅํ์ง ์๊ธฐ ๋๋ฌธ์
ํ๋ก๊ทธ๋จ์ด ์ปดํ์ผ๋๋๋ก ๋์์ค ๊ฒ์ด๋ค.
๋ ์ ํ๋ฒํธ์ ์ง์ญ ์ฝ๋๊ฐ ๊ฐ์ ์ ์์ผ๋, ๋น๊ต ๋ฐฉ์์ ๋ ๋ค๋ฌ์ด์ผ ํ๋ค.
์ฌ๊ธฐ์ ๋ ๋ฒ์งธ ๋น๊ต์ ์์ฑ ๋ฉ์๋์ธ thenComparingInt๊ฐ ๋ฑ์ฅํ๋ค.
thenComparingInt๋ Comparator์ ์ธ์คํด์ค ๋ฉ์๋๋ก, int ํค ์ถ์ถ์ ํจ์๋ฅผ ์ ๋ ฅ๋ฐ์ ๋ค์ ๋น๊ต์๋ฅผ ๋ฐํํ๋ค.
(์ด ๋น๊ต์๋ ์ฒซ ๋ฒ์งธ ๋น๊ต์๋ฅผ ์ ์ฉํ ๋ค์ ์๋ก ์ถ์ถํ ํค๋ก ์ถ๊ฐ ๋น๊ต๋ฅผ ์ํํ๋ค.)
thenComparingInt๋ ์ํ๋ ๋งํผ ์ฐ๋ฌ์ ํธ์ถํ ์ ์๋ค.
์ ์ฝ๋์์๋ 2๊ฐ๋ฅผ ์ฐ๋ฌ์ ํธ์ถํ์ผ๋ฉฐ ๊ทธ์ค ์ฒซ ๋ฒ์งธ์ key๋ก๋ prefix๋ฅผ, ๋ ๋ฒ์งธ์ ํค๋ก๋ lineNum์ ์ฌ์ฉํ๋ค.
์ด๋ฒ์ thenComparingInt๋ฅผ ํธ์ถํ ๋ ํ์ ์ ๋ช ์ํ์ง ์์๋ค.
์๋ํ๋ฉด ์๋ฐ์ ํ์ ์ถ๋ก ๋ฅ๋ ฅ์ด ์ด ์ ๋๋ ์ถ๋ก ํด๋ผ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Comparator๋ ์๋ง์ ๋ณด์กฐ ์์ฑ ๋ฉ์๋๋ค๋ก ์ค๋ฌด์ฅํ๊ณ ์๋ค.
long๊ณผ double์ฉ์ผ๋ก๋ thenComparingLong๊ณผ thenComparingDouble์ด ์๋ค.
short์ฒ๋ผ ๋ ์์ ์ ์ ํ์ ์๋ ์ PhoneNumber์ฒ๋ผ int์ฉ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก float์ double์ฉ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
Comparator ์ด๋ ๊ฒ ์๋ฐ์ ๋ชจ๋ ์ซ์์ฉ ๊ธฐ๋ณธ ํ์ ์ ๋ํ ๋น๊ต์ ์์ฑ ๋ฉ์๋๋ฅผ ์ง์ํ๋ค.
๋ํ ๊ฐ์ฒด ์ฐธ์กฐ์ฉ ๋น๊ต์ ์์ฑ ๋ฉ์๋๋ ์ค๋น๋์ด ์๋ค.
์ฐ์ comparing ์ด๋ผ๋ ์ ์ ๋ฉ์๋ 2๊ฐ๊ฐ ๋ค์ค์ ์๋์ด ์๋ค.
์ฒซ ๋ฒ์งธ๋ ํค ์ถ์ถ์๋ฅผ ๋ฐ์์ ๊ทธ ํค์ ์์ฐ์ ์์๋ฅผ ์ฌ์ฉํ๋ค.
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
๋ ๋ฒ์งธ๋ ํค ์ถ์ถ์ ํ๋์ ์ถ์ถ๋ ํค๋ฅผ ๋น๊ตํ ๋น๊ต์๊น์ง ์ด 2๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋๋ค.
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator) {
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
๋ํ thenComparing์ด๋ ์ธ์คํด์ค ๋ฉ์๋๊ฐ 3๊ฐ ๋ค์ค์ ์๋์ด ์๋ค.
์ฒซ ๋ฒ์งธ๋ ๋น๊ต์ ํ๋๋ง ์ธ์๋ก ๋ฐ์ ๊ทธ ๋น๊ต์๋ก ๋ถ์ฐจ ์์๋ฅผ ์ ํ๋ค.
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
๋ ๋ฒ์งธ๋ ํค ์ถ์ถ์๋ฅผ ์ธ์๋ก ๋ฐ์ ๊ทธ ํค์ ์์ฐ์ ์์๋ก ๋ณด์กฐ ์์๋ฅผ ์ ํ๋ค.
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
๋ง์ง๋ง ์ธ ๋ฒ์งธ๋ ํค ์ถ์ถ์์ ์ถ์ถ๋ ํค๋ฅผ ๋น๊ตํ ๋น๊ต์๊น์ง ์ด 2๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋๋ค.
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
๊ฐ์ ์ฐจ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฒซ ๋ฒ์งธ ๊ฐ์ด ๋ ๋ฒ์งธ ๊ฐ๋ณด๋ค ์์ผ๋ฉด ์์๋ฅผ, ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด 0์, ์ฒซ ๋ฒ์งธ ๊ฐ์ด ํฌ๋ฉด ์์๋ฅผ ๋ฐํํ๋ compareTo๋ compare ๋ฉ์๋๋ฅผ ๋ง๋ค๋ฉด ์๋๋ค.
static Comparator<Object> hashCodeOrder = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.hashCode() - o2.hashCode();
}
}
์ด ๋ฐฉ์์ ์ ์ ์ค๋ฒํ๋ก๋ฅผ ์ผ์ผํค๊ฑฐ๋ IEEE 754 ๋ถ๋์์์ ๊ณ์ฐ ๋ฐฉ์์ ๋ฐ๋ฅธ ์ค๋ฅ๋ฅผ ๋ผ ์ ์๋ค.
๋ํ ์ด๋ฒ ์์ดํ ์์ ์ค๋ช ํ ๋ฐฉ๋ฒ๋๋ก ๊ตฌํํ ์ฝ๋๋ณด๋ค ์๋ฑํ ๋น ๋ฅด์ง๋ ์์ ๊ฒ์ด๋ค.
์๋์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ ์ค ํ๋๋ฅผ ์ ํํ์ฌ ๊ตฌํํด์ผ ํ๋ค.
static Comparator<Object> hashCodeOrder = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
}
static Comparator<Object> hashCodeOrder = Comparator.comparingInt(o -> o.hashCode());