首先我们考虑一个场景:有一个整型数组,我们希望通过调用工具类的sort方法对数组进行排序。请看下面的代码:
公共类策略{ public static void main(String[] args) { int[] arr={5, 3, 1, 7, 2}; new DataSorter().sort(arr);//调用排序工具类for (int i=0; i arr.length; i++){ System.out.println(arr[i]); } }}class DataSorter{//排序的工具类public void sort(int[] arr){ //调用sort方法进行排序,这里使用冒泡排序for(int i=arr.length - 1; i 0; i --){ for(int j=0; j i; j++){ if(arr[j] arr[j + 1]) 交换(arr, j, j + 1); } } } private void swap(int[] arr, int i, int j){ int temp=arr[i]; arr[i]=arr[j]; arr[j]=温度; }}
通过上面的代码,我们可以轻松的对整型数组进行排序,那么如果有新的需求,我们需要对浮点型数据进行排序。排序工具类应该怎么做呢?
那么如果我继续问,如果我现在想要对一只猫进行分类,我该怎么办?猫类如下:
class Cat{ private int Age;//猫的年龄private int Weight;//猫的体重//获取/设置方法.} 你可能照原样回答,复制一个排序算法,修改方法参数,然后指定比较地点的比较猫的年龄或体重,对吧?
![]()
public void sort(Cat[] arr){//以cat数组为参数for(int i=arr.length - 1; i 0; i--){ for(int j=0; j i; j++){ if( arr[j].getAge() arr[j + 1].getAge())//比较swap(arr, j, j + 1);但仔细想一想,如果要继续比较小狗、鸡、鸭子等各种对象,这个排序工具类的代码量岂不是会变得很大?为了让排序算法的复用性更强,我们希望排序工具中的sort() 方法可以对调用它的任何对象进行排序。
您可能认为要能够对任何对象进行排序,您可以将sort() 方法的参数更改为Object 类型。这个方向是对的,但问题是,当你得到两个Object类型的对象时,你应该按照什么规则进行比较?
这时我们自然希望调用工具类进行排序的对象有自己的比较规则,这样在排序时可以直接调用该对象的排序规则。
我们将比较规则抽象为Comparable接口。所有需要比较的类都必须实现Comparable接口并定义自己的比较规则,这就是CompareTo()方法。
这样,我们在打包工具的时候,就可以直接比较实现了Comparable接口的对象,而不用担心比较的细节。
![]()
public class Strategy {public class Strategy { public static void main(String[] args) {//Integer[] arr={5, 3, 1, 7, 2};//注意将int改为Integer,Integer为对象的子类Cat[] arr={new Cat(3, 3), new Cat(1, 1), new Cat(5, 5)}; DataSorter ds=new DataSorter(); ds.sort(arr); for(int i=0; i arr.length; i++){ System.out.println(arr[i]); } } }}}class DataSorter{//排序的工具类public void sort(Object[] arr ){//参数类型为Object for(int i=arr.length - 1; i 0; i--){ for (int j=0; j i; j++){ 可比较c1=(可比较) arr[j]; //先转换为Comparable类型Comparable c2=(Comparable) arr[j + 1]; if(c1.CompareTo(c2)==1)//调用CompareTo()进行比较,不管具体实现如何swap(arr, j, j + 1); } } } private void swap(Object[] arr, int i, int j){ Object temp=arr[i]; arr[i]=arr[j]; arr[j]=温度; }}类Cat 实现Comparable{ private int Age;私有int 权重; @Override public int CompareTo(Object o) { if(o instanceof Cat){//首先判断传入的对象是否是Cat类对象,如果不是则抛出异常Cat c=(Cat) o; if(this.age c.age) 返回1; else if (this.age c.age) 返回-1;否则返回0; } 抛出null==o ?新的ClassCastException(); } //get/set . //toString() .}interface Comparable{ public int CompareTo(Object o);}
相信看完上面Comparable接口的由来,你就会明白了设计感觉比较好,但是还是有漏洞。在Cat 类的CompareTo() 方法中,猫的比较策略是硬编码的。现在我们根据猫的年龄来比较它们。如果有一天我们要比较猫根据猫的体重比较大,那么我需要再次修改源代码。有没有扩展性更好的设计?
我们可以允许用户自己定义一个比较器类,并且可以根据用户指定的比较器来比较对象的大小。
整个逻辑就是:如果这个对象需要比较,那么它必须实现Comparable接口,但是具体怎么比较,是通过具体的Comparator比较器来比较的。
当然,这里少不了多态。我们首先要定义一个比较器接口Comparator。用户的比较器需要实现Comparator接口。下面是代码:
![]()
公共类策略{ public static void main(String[] args) { Cat[] arr={new Cat(3, 3), new Cat(1, 1), new Cat(5, 5)}; DataSorter ds=new DataSorter(); ds.sort(arr); for(int i=0; i arr.length; i++){ System.out.println(arr[i]); } } }}class DataSorter{//用于排序的工具类public void sort(Object[] arr){//参数类型为Object for(int i=arr.length - 1; i 0; i--){ for( int j=0; j i; j++){ Comparable c1=(Comparable) arr[j];//先转换为Comparable类型Comparable c2=(Comparable) arr[j + 1]; if(c1.CompareTo(c2)==1)//已经转换为在幕后使用Comparator 比较定义的规则swap(arr, j, j + 1); } } } private void swap(Object[] arr, int i, int j){ Object temp=arr[i]; arr[i]=arr[j]; arr[j]=温度; }}类Cat 实现Comparable{ private int Age;私有int 权重; private Comparator comparator=new CatAgeComparator();//默认持有年龄比较器@Override public int CompareTo(Object o) { return comparator.Compare(this, o);//调用比较器进行比较,而不是写比较直接在这里规则} //get/set/toString .}interface Comparable{ public int CompareTo(Object o); }interface Comparator{ public int Compare(Object o1, Object o2);}//用户定义的比较器,根据猫的年龄段进行比较CatAgeComparator 实现Comparator{ @Override public int Compare(Object o1, Object o2) { Cat c1=(猫)o1;猫c2=(猫) o2; if(c1.getAge() c2.getAge()) 返回1;否则if(c1.getAge() c2.getAge()) 返回-1;否则返回0; }}//比较器类CatWeightComparator 实现Comparator{ @Override public int Compare(Object o1, Object o2) { Cat c1=(Cat) o1;猫c2=(猫) o2 ; if(c1.getWeight() c2.getWeight()) 返回1;否则if(c1.getWeight() c2.getWeight()) 返回-1;否则返回0; }}
在上面的例子中,我们自己定义了Comparable接口和Comparator接口。事实上,这两个接口是Java原生的。通过上面的代码示例,你一定也知道为什么会存在这两个接口了。
事实上,Comparable定义了一种比较策略。你可以把这里的策略理解为一个函数。然而,一旦策略可用,我们仍然需要具体的策略实现,因此我们有Comparator 接口。
我认为在比较对象的Comparable和Comparator中使用策略模式有以下好处:
用户评论
这个比较类的游戏让我对Java集合框架有了深入的理解!在面对各种`Comparable`与`Comparator`时,我体验到了如何根据特定规则来定义元素之间的关系。
有10位网友表示赞同!
`Comparable`真是个神奇的类,当我在游戏中给对象实现此接口时,一切都变得那么简洁。它让代码在排序任务中流畅运行。
有8位网友表示赞同!
通过这个游戏,我学会了`Comparator.compare`方法的奥秘,原来自定义比较规则可以如此灵活和强大!
有19位网友表示赞同!
`Comparable`与`Comparator`之间的差异是我在这个游戏中探索的第一个知识点,它们给我带来了新的编程视角。
有11位网友表示赞同!
`Comparable`是关于对象间的自然排序魔法!当我在游戏中为动物类型实现这一特性时,看到数组按名字或能力排序真的很爽。
有17位网友表示赞同!
游戏让我理解了为什么要用`Comparator`而不用原生的`compareTo()`方法对集合进行比较。通过实战,我发现后者更具可移植性和灵活性。
有15位网友表示赞同!
`Comparable`在游戏中提供了对象自定义排序的基础框架,这使得构建复杂数据结构变得一目了然。
有16位网友表示赞同!
在对比类(`Comparable`)的世界中,我学会了如何赋予自己的代码"自动排序"的能力,简直是编程界的魔法。
有16位网友表示赞同!
游戏中的挑战要求我在不同场景使用`Comparator`,这个过程让我对它的重要性有了深刻认识。原来自定义比较规则可以解决很多复杂问题!
有14位网友表示赞同!
`Comparable`与`Comparator`之间的选择在性能优化中至关重要,在游戏中我学会了如何根据实际情况做出合适的抉择。
有6位网友表示赞同!
通过深入学习,我发现`Comparator`能够更精确地掌控特定条件下的排序方式,这让我的代码更加优雅和高效。
有10位网友表示赞同!
每当我在游戏中需要对非天然可比对象进行排序时,`Comparator`就像救星一样给我指引明路。
有7位网友表示赞同!
`Comparable`让我认识到定义类内自然行为的便利性,游戏中的例子让我深深佩服Java的设计哲学。
有13位网友表示赞同!
通过这个小游戏,我不仅学习了编程技巧,还增强了逻辑思维能力。`Comparable`和`Comparator`让问题解决了那么自然而然!
有8位网友表示赞同!
在面对复杂数据结构时,`Comparator`提供了一种优雅的方式进行比较和排序。游戏帮我理解到其应用场景的广泛性。
有7位网友表示赞同!
`Comparable`让我体验了"内部秩序"带来的编码乐趣,在没有依赖外界的情况下定义元素之间的顺序真是太棒了:
有6位网友表示赞同!
在这个游戏中通过对比`Comparable`与`Comparator`,我发现前者虽然方便但灵活性较低;而后者则更强大且适用范围更广。
有13位网友表示赞同!
`Comparable`和`Comparator`的使用策略是我在游戏中的一个重要发现。通过实践它们,我学会了权衡两者在不同场景下的应用价值。
有16位网友表示赞同!