Философия Java3
Шрифт:
В Java функциональность сравнения может выражаться двумя способами. Первый основан на «естественном» методе сравнения, который включается в класс при реализации java.lang.Comparable — очень простого интерфейса с единственным методом compareTo. В аргументе метод получает другой объект того же типа. Он выдает отрицательное значение, если текущий объект меньше аргумента, нуль при равенстве и положительное значение, если текущий объект больше аргумента.
В следующем примере класс реализует Comparable, а для демонстрации совместимости используется метод стандартной библиотеки Java Arrays.sort:
//: arrays/CompType.java
//
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
public class CompType implements Comparable<CompType> { int i. int j;
private static int count = 1; public CompType(int nl, int n2) { i = nl; J = n2;
}
public String toStringO {
String result = "[i = " + i + J = " + j + "]"; if(count++ % 3 == 0)
result += "\n"; return result;
}
public int compareTo(CompType rv) {
return (i < rv.i ?
– 1 : (i == rv.i ? 0 : 1));
}
private static Random r = new Random(47); public static Generator<CompType> generatorO { return new Generator<CompType> { public CompType nextO {
return new CompType(r.nextInt(100),r.nextInt(100));
}
}:
}
public static void main(String[] args) { CompType[] a =
Generated, array (new CompType[12], generatorO); print("перед сортировкой;"); pri nt(Arrays.toStri ng(a)); Arrays.sort(a); print("после сортировки;");
print(Arrays.toString(a)); продолжение &
}
} /* Output: перед сортировкой:
[[1 = 58, j = 55], [i = 93. j = 61]. [i =61. j = 29] . [i = 68, j = 0], [i = 22, j = 7]. [i = 88, j = 28] , [i = 51, j = 89], [i = 9, j = 78], [i = 98. j = 61]
, [i = 20, j = 58]. [i = 16, j = 40], [i - 11. j - 22] ]
после сортировки:
CCi = 9. j = 78], [i - 11. j - 22], [i - 16. j - 40]
. [i = 20. j = 58]. [i = 22, j = 7]. [i = 51. j = 89]
. [i = 58. j = 55]. [i =61. j = 29]. [i = 68. j = 0]
. [i = 88. j = 28]. [i = 93. j = 61]. [i = 98. j = 61] ]
*///:-
Определяя метод сравнения, вы несете полную ответственность за принятие решения о его результатах. В приведенном примере в сравнении используются только значения i, а значения j игнорируются.
Метод generator производит объект, реализующий интерфейс Generator, создавая анонимный внутренний класс. Объект строит объекты CompType, инициализируя их случайными значениями. В main генератор заполняет массив CompType, который затем сортируется. Если интерфейс Comparable не реализован, то при попытке вызова sort произойдет исключение ClassCastException. Это объясняется тем, что sort преобразует свой аргумент к типу Comparable.
Теперь представьте, что вы получили класс, который не реализует интерфейс Comparable... а может быть, реализует, но вам не нравится, как он работает, и вы хотели бы задать для типа другой метод сравнения.
Для решения проблемы создается отдельный класс, реализующий интерфейс Comparator. Он содержит два метода, compare и equals. Впрочем, вам практически никогда не придется реализовывать equals — разве что при особых требованиях по быстродействию, потому что любой создаваемый класс неявно наследует от класса Object метод equals.Класс Collections содержит метод reverseOrder, который создает Comparator для порядка сортировки, обратного по отношению к естественному. Он может быть применен к CompType:
//: arrays/Reverse.java
// Метод Col lections.reverseOrderO
import java util *;
i mport net.mi ndvi ew.uti1.*,
import static net.mindview.util.Print.*;
public class Reverse {
public static void main(String[] args) { CompTypeC] a = Generated.array(
new CompType[12], CompType generatorO); print("перед сортировкой "); print(Arrays.toString(a)). Arrays.sort(a. Col lections. reverseOrderO). print("после сортировки:"); pri nt(Arrays.toStri ng(a));
} /* Output: перед сортировкой:
[[i = 58. j = 55]. [i = 93. j = 61]. [i =61. j = 29] . [i = 68. j = 0]. [i = 22. j = 7]. [i - 88. j - 28] . [i = 51. j = 89]. [i = 9. j = 78]. [i = 98. j = 61]
. [i = 20. j = 58]. [i =16. j = 40]. [i - 11. j - 22] ]
после сортировки:
[[i - 98. j - 61]. [i =93. j = 61]. [i =88. j = 28] . [i = 68. j = 0]. [i = 61. j = 29]. [i = 58. j = 55] . [i = 51. j = 89]. [i = 22. j = 7]. [i = 20. j = 58]
. [i = 16. j = 40]. [i = 11. j = 22]. [i = 9. j = 78] ]
*///:-
Наконец, вы можете написать собственную реализацию Comparator. В следующем примере объекты CompType сравниваются по значениям]' вместо i:
//: arrays/ComparatorTest.java
// Реализация Comparator
import java.util.*:
import net.mindview.util.*:
import static net.mindview.util.Print.*:
class CompTypeComparator implements Comparator<CompType> { public int compare(CompType ol. CompType o2) {
return (ol.j < o2.j ?
– 1 : (ol.j == o2.j ? 0 : 1)):
}
}
public class ComparatorTest {
public static void main(String[] args) { CompTypeC] a = Generated.array(
new CompType[12], CompType.generatorO); print("перед сортировкой:"): print(Arrays.toString(a)): Arrays.sort(a. new CompTypeComparatorO); print("после сортировки:"): print(Arrays.toString(a));
}
} /* Output: перед сортировкой:
[[i = 58. j = 55]. [i = 93. j = 61]. [i = 61. j = 29] . [i = 68. j = 0]. [i = 22. j = 7]. [i = 88. j = 28] . [i = 51. j = 89]. [i = 9. j = 78]. [i = 98. j = 61]
. [i = 20. j = 58]. [i = 16. j = 40]. [i = 11. j = 22] ]
после сортировки:
[[1 = 68. j = 0]. [i = 22. j = 7]. [i - 11. j - 22]
. [i = 88. j = 28]. [i = 61. j = 29]. [i = 16. j = 40]
. [i = 58. j = 55]. [i = 20. j = 58]. [i = 93. j = 61]
. [i = 98. j = 61]. [i = 9. j = 78]. [i = 51. j = 89] ]