第十七天

java里的数据类型中,number数据类型,比如intdouble还有字符串类型Stirng等等,都是能够比较大小的,为什么?原因就是他们都实现了一个接口就是Comparable接口,现实的应用中我们可能会遇到想让自定义的类的对象可以进行排序,前提就是需要这里类的对象能比较大小,怎么办?

 

接口Comparable

我们知道数字是可以用> < == 等运算符进行比较大小的,其实在字符串中也有CompareTo方法,这个方法可以用于比较字符串大小的,根据字典顺序进行排序。

Str1.compareTo(Str2);

其返回的是一个int类型值。若Str1等于参数字符串Str2字符串,则返回0;若该Str1按字典顺序小于参数字符串Str2,则返回值小于0;若Str1按字典顺序大于参数字符串Str2,则返回值大于0

 

Java中很多类也都有CompareTo方法,甚至于排序算法的底层也是依赖于比较的,而这个比较就是依赖于各种数据类型的CompareTo或者Compare方法。Java中所有的compareTo方法都源于一个接口,那就是Comparable。这个接口只有一个方法,那就是CompareTo。所有想要具有比较功能的类,都建议实现这个接口,而非是自己定义这个功能,这是面向对象的概念(将具有相同功能的事物抽象到一个共同的类或接口),并且为了多态也建议通过实现接口来进行向上转型,通过接口来操作具体实现,这也是面向接口编程要求我们做的。下面我们来具体了解一下Comparable接口。

 

先分析一下Strnig类的compareToequals方法:

 

package coursetest;

public class Person implements Comparable<Person> {
    private Integer id;//建议做成id的包装类
    private String name;//定义字符串类型变量 变量名为name    
    private int age;//定义int整型变量 变量名为age
     //为三个私有变量构造get set方法 使数据可以在私有的情况赋值和取出
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
      //重写compareTo方法 
    @Override
    public int compareTo(Person o) {//根据id比大小
        // p1.compartTo(p2);
        //p1>p2:正整数,p1==p2:0;p1<p2:负整数
//        if(this.id>o.id) return 1;
//        if(this.id==o.id) return 0;
//        return 1;
        return this.id - o.id; //一句话搞定上面三行代码
    }
  //重写hashCode方法
    @Override
    public int hashCode() {//重写hashCode
        // TODO Auto-generated method stub
        return id.hashCode();
    }
    //重写equals方法,提供自定义的相等标准   参数名为obj
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Person) {    //是否obj变量类型可以转换为Person变量类型
            Person other =(Person)obj;//强制转换,就是将obj类型强制转换成Person类型
            if (this.id == other.id) {
                return true;
            }else {
                return false;
            }
        }
        return false;
    }
   //重写toString方法
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
//重写toString() 可以理解为是对对象在打印输出时候的一种格式化。这样做符合业务逻辑,显示结果人性化   
}
package coursetest;

import java.util.Arrays;

public class Demo {
    public static void main(String[] args) {
        Person p1 = new Person();//对象1
        p1.setId(1);
        Person p2 = new Person();//对象2
        p2.setId(2);
        Person p3 = new Person();//对象3
        p3.setId(3);
        Person p4 = new Person();//对象4
        p4.setId(4);
        
        Person [] arr = new Person [] {p4,p3,p1,p2};//定义一个数组,将对象1234放入
        System.out.println(Arrays.toString(arr));//打印数组
        Arrays.sort(arr);//调用array.sort方法为数组排序
        System.out.println(Arrays.toString(arr));//再次打印数组
    }
}

注意:一般情况下,compareToequals方法应该是统一的,equals返回truecompareTo应用返回0;所以实现了compareTo方法就要覆盖equals方法,让两者保持一致!而且前面又讲了覆盖equals方法,就一定要重写hashCode方法。

最后compareable接口,我们自定义一个Person类来实践一下!

定义要给Person类,实例化5Person类的对象,放到数组里,然后用Arrays.sort(数组);工具对数组进行排序! 

接口Comparator

1. 我们需要控制某个类的次序,而该类不支持排序(即没有实现Comparable接口)。那么,我们可以创建一个该类的比较器,这个比较器只需要实现Comparator。若一个类实现了Comparator接口,则它一定要实现compare(T o1,T o2)方法,但不一定要实现equals(Object obj)方法;

2. 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过Comparator来实现比较算法进行排序;为了使用不同的排序标准做准备,比如:升序、降序

在上面的例子基础上,使用一些接口Comparator,然后用Arrays.sort(数组,比较器);对数组排序输出一下!

 

public class Dog {
    private Integer id;//建议做成id的包装类
    private String name;//定义字符串类型变量 变量名为name    
    private int age;//定义int整型变量 变量名为age
    //下面为三个私有变量的get set方法
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //覆盖toString方法
    @Override
    public String toString() {
        return "Dog [id=" + id + ", name=" + name + ", age=" + age + "]";
    }    
}
package coursetest;

import java.util.Comparator;

public class DogComparetor2 implements Comparator<Dog>{
     //覆盖compare方法
    @Override
    public int compare(Dog o1, Dog o2) {
        
        return o1.getAge() - o2.getAge();//两个对象的年龄差
    }
}
package coursetest;

import java.util.Comparator;

public class DogComparetor2 implements Comparator<Dog>{
     //覆盖compare方法
    @Override
    public int compare(Dog o1, Dog o2) {
        
        return o1.getAge() - o2.getAge();//两个对象的年龄差
    }
}
package coursetest;

import java.util.Arrays;

public class Demo {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.setId(1);
        dog1.setAge(2);
        Dog dog2 = new Dog();
        dog2.setId(2);
        dog2.setAge(5);
        Dog dog3 = new Dog();
        dog3.setId(3);
        dog3.setAge(1);
        Dog[] arr = new Dog[] { dog2, dog1, dog3 };// 定义一个数组,将对象123放入
        System.out.println(Arrays.toString(arr));// 打印数组
        //进行Id排序
        Arrays.sort(arr,new DogComparetor());//调用自己创建的DogComparetor比较器
//Arrays.sort(arr,new DogComparetor2());
//调用自己创建的DogComparetor2比较器进行年龄排序
        System.out.println(Arrays.toString(arr));// 打印数组
    }
}

CompareableComparator两者比较总结:

1. 前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用

2. Comparable是排序接口;若一个类实现了Comparable接口,就意味着该类支持排序;而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个该类的比较器来进行排序。

3. Comparable相当于内部比较器,而Comparator相当于外部比较器

4. Comparable是通用的接口,用户可以实现它来完成自己特定的比较,而Comparator可以看成是一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成是一种设计模式,将算法和数据分离。

 

 

 

 

 

 

java7里面新增的Objects类,该类的主要用途是将操作对象的一切常用操作进行的封装。包括hashCodeequals等。 java87的基础上又新增一些方法。

知识点一:Objects类简介

本类由一些操作对象的静态工具方法构成,这些工具方法包括了非空检查方法的非空参数检查比较对象的hashCode为对象返回一个字符串比较两个对象

知识点二:Objects特点

1.该类是使用final修饰,不能被继承 2.该类的构造方法被私有化(使用private修饰),不能直接创建对象 3.该类中所有的方法都是静态方法,可以使用类型直接调用(对应2,该类不需要创建对象)

知识点三:Objects内方法介绍

//比较两个对象是否相等(首先比较内存地址,然后比较a.equals(b),只要符合其中之一返回true

public static boolean equals(Object a, Object b);

 

//深度比较两个对象是否相等(首先比较内存地址,相同返回true;如果传入的是数组,则比较数组内的对应下标的值是否相同)

public static boolean deepEquals(Object a, Object b);

import java.util.Arrays;
import java.util.Objects;

public class Demo {
    public static void main(String[] args) {
        Integer [] a1 = new Integer [] {1,2,3};
        Integer [] a2 = new Integer [] {1,2,3};
        Integer [] a3 = new Integer [] {1,3,3};
        System.out.println(Objects.deepEquals(a1, a2));//true
        System.out.println(Objects.deepEquals(a1, a3));//false        
    }
}

//返回对象的hashCode,若传入的为null,返回0

public static int hashCode(Object o);

import java.util.Objects;

public class Demo {
    public static void main(String[] args) {
        String string = "a";
        String s1 = null;
        System.out.println(string.hashCode());//97
        //System.out.println(s1.hashCode());//java.lang.NullPointerException报异常
        System.out.println(Objects.hashCode(s1));//0
    }

//返回传入可变参数的所有值的hashCode的(加工后)总和(这里说总和有点牵强,具体参考Arrays.hashCode()方法)

public static int hash(Object... values);

public class Demo {
    public static void main(String[] args) {
    System.out.println("a".hashCode());//97
    System.out.println(Objects.hashCode("a"));//97
    System.out.println(Objects.hash("a"));//128
    }
}

1. 

//返回对象的String表示,若传入null,返回null字符串

public static String toString(Object o)

 

import java.util.Objects;

public class Demo {
    public static void main(String[] args) {
    String s = "aaa";
    System.out.println(s.toString());//aaa
    System.out.println(Objects.toString(s));//aaa
    String s1 = null;
    //System.out.println(s1.toString());//报错
    System.out.println(Objects.toString(s1));//null
    }
}

//返回对象的String表示,若传入null,返回默认值nullDefault

public static String toString(Object o, String nullDefault)

import java.util.Objects;

public class Demo {
    public static void main(String[] args) {
    String s = null;
    System.out.println(Objects.toString(s,"default"));//default
    }
}

//使用指定的比较器c 比较参数a和参数b的大小(相等返回0a大于b返回整数,a小于b返回负数)

public static <T> int compare(T a, T b, Comparator<? super T> c)

 

//如果传入的objnull抛出NullPointerException,否者返回obj

public static <T> T requireNonNull(T obj)

 

//如果传入的objnull抛出NullPointerException并可以指定错误信息message,否者返回obj

public static <T> T requireNonNull(T obj, String message)

import java.util.Objects;

public class Demo {
    public static void main(String[] args) {
    String s = null;
    Objects.requireNonNull(s,"不能为空");
    }
}

//判断传入的obj是否为null,是返回true,否者返回false

public static boolean isNull(Object obj)

 

//判断传入的obj是否不为null,不为空返回true,为空返回false(和isNull()方法相反)

public static boolean nonNull(Object obj)

 

//如果传入的objnull抛出NullPointerException并且使用参数messageSupplier指定错误信息,否者返回obj

public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier)

 

知识点五:总结

Objects类给我们提供了一些常用的操作对象的方法,我们可以直接使用,这是非常方便的。尤其是requireNonNull()方法, 在我们写方法时需要判断传入的参数是否为null可以使用该方法及其方便。

 

 

 

 

 

 

 

 

 

 

java里的数据类型中,number数据类型,比如intdouble还有字符串类型Stirng等等,都是能够比较大小的,为什么?原因就是他们都实现了一个接口就是Comparable接口,现实的应用中我们可能会遇到想让自定义的类的对象可以进行排序,前提就是需要这里类的对象能比较大小,怎么办?

 

接口Comparable

我们知道数字是可以用> < == 等运算符进行比较大小的,其实在字符串中也有CompareTo方法,这个方法可以用于比较字符串大小的,根据字典顺序进行排序。

Str1.compareTo(Str2);

其返回的是一个int类型值。若Str1等于参数字符串Str2字符串,则返回0;若该Str1按字典顺序小于参数字符串Str2,则返回值小于0;若Str1按字典顺序大于参数字符串Str2,则返回值大于0

 

Java中很多类也都有CompareTo方法,甚至于排序算法的底层也是依赖于比较的,而这个比较就是依赖于各种数据类型的CompareTo或者Compare方法。Java中所有的compareTo方法都源于一个接口,那就是Comparable。这个接口只有一个方法,那就是CompareTo。所有想要具有比较功能的类,都建议实现这个接口,而非是自己定义这个功能,这是面向对象的概念(将具有相同功能的事物抽象到一个共同的类或接口),并且为了多态也建议通过实现接口来进行向上转型,通过接口来操作具体实现,这也是面向接口编程要求我们做的。下面我们来具体了解一下Comparable接口。

 

先分析一下Strnig类的compareToequals方法:

 

注意:一般情况下,compareToequals方法应该是统一的,equals返回truecompareTo应用返回0;所以实现了compareTo方法就要覆盖equals方法,让两者保持一致!而且前面又讲了覆盖equals方法,就一定要重写hashCode方法。

 

最后compareable接口,我们自定义一个Person类来实践一下!

定义要给Person类,实例化5Person类的对象,放到数组里,然后用Arrays.sort(数组);工具对数组进行排序!

 

 

接口Comparator

1. 我们需要控制某个类的次序,而该类不支持排序(即没有实现Comparable接口)。那么,我们可以创建一个该类的比较器,这个比较器只需要实现Comparator。若一个类实现了Comparator接口,则它一定要实现compare(T o1,T o2)方法,但不一定要实现equals(Object obj)方法;

2. 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过Comparator来实现比较算法进行排序;为了使用不同的排序标准做准备,比如:升序、降序

 

在上面的例子基础上,使用一些接口Comparator,然后用Arrays.sort(数组,比较器);对数组排序输出一下!

 

 

CompareableComparator两者比较总结:

1. 前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用

2. Comparable是排序接口;若一个类实现了Comparable接口,就意味着该类支持排序;而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个该类的比较器来进行排序。

3. Comparable相当于内部比较器,而Comparator相当于外部比较器

4. Comparable是通用的接口,用户可以实现它来完成自己特定的比较,而Comparator可以看成是一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成是一种设计模式,将算法和数据分离。

 

 

 

 

原文地址:https://www.cnblogs.com/jikebin/p/12623010.html