比较接口的使用

所以说以后的自定义的类型,如果说要进行比较大小,那么必须要让这个类具有比较的功能

 一)Compable接口:

Comparable是排序接口,若一个类实现了Comparable接口,就意味着该类支持排序。

实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序

注意:Compable接口里面的compareTo方法是一个空方法

1)继承comparable接口,里面的泛型参数要写里面的比较的类型,重写CompareTo方法,里面加上泛型参数,泛型参数里面加上要比较的类型,这种写法,对类的侵入性比较强,如果一个类实现了这个Comparable接口,那么就意味着该类支持排序,或者说对象的列表或者数组可以进行自动排序,一旦写好之后,不敢轻易改动

2)一个类型实现了Compareable接口,表明了这个类具有了可排序的功能或者说标准,两个对象通过Compareable接口中的compareTo方法的返回值来比较大小

Comparable接口的源码:

public interface Comparable<T>{
   public int compareTo(T o);
}

为什么要实现Comparable接口?
一个类型实现了Comparator接口,表明这个类具有了可排序的功能或者标准,两个对象可以通过Compareable接口中的compareTo方法的返回值来进行比较大小

 static class Student implements Comparable<Student>
    {
        public String name;
        public int age;
        public Double score;

        public Student(String name, int age,Double score) {
            this.name = name;
            this.age = age;
            this.score=score;
        }
        @Override
        public int compareTo(Student o) {//谁调用CompareTo谁就是this
            if(this.age>o.age) return 1;//在这里也可以同构比较年龄
            else if(this.age==o.age) return 0;
            else{
                return -1;
            }
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", score=" + score +
                    '}';
        }
    }

    public static void main(String[] args) {
        Student student1=new Student("李佳伟",15,23.9);
        Student student2=new Student("李佳鑫",34,89.9);
        Student student3=new Student("周云刚",89,10.9);
        Student[] arr1={student1,student2,student3};
        Arrays.sort(arr1);
        System.out.println(Arrays.toString(arr1));
//如果我们不实现这个接口,那么直接排序会造成报错
//两个对象进行比较        
       if(student1.compareTo(student2)>0)
          {
            System.out.println("student1的年龄比student2的年龄大");
          }
}

我们不进行实现这个接口,那么一定会出现报错,不知道按照什么样的规则来进行比较,会出现ClassCastException,类型转换异常,不实现这个接口,都不知道按照什么来进行比较,也就是说你自己定义的类型,要具有可比较的功能

1)首先定义一个学生对象,再定义一个学生对象数组,我们将对象数组中的元素继续进行排序,按照年龄来进行排序,比如说按照年龄进行升序排序,直接传入数组名就可以了


@Data
class Student{
    public String username;
    public String password;
    public int age;
    public Student(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }
}
public class HelloWorld
{
    public static void main(String[] args) {
        Student student1=new Student("李佳伟","12503487",12);
        Student student2=new Student("李佳鑫","778891",89);
        Student student3=new Student("张钟俊","9090",86);
        Student[] students=new Student[3];
        Arrays.sort(students);
    }
}

2)当我们调用Arrays.sort(students)的时候,可以发现我们的源码类型可以将数组元素强制转换成Comparable类型,而我们自定义的类和我们的Comparable毫不相关,Student类是没有compareTo方法的此时去跳转到异常提示的位置查看,可以发现源码中是将数组元素强制转换为Comparable类型,再去调用其中的compareTo方法,而此时我们自定义类型Student与Comparable毫不相干

package com.example.demo;

import lombok.Data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Data
class Student implements Comparable<Student>{
    public String username;
    public String password;
    public int age;
    public Student(String username, String password, int age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }
}
public class HelloWorld
{
    public static void main(String[] args) {
        Student student1=new Student("李佳伟","12503487",12);
        Student student2=new Student("李佳鑫","778891",89);
        Student student3=new Student("张钟俊","9090",86);
        Student[] students=new Student[3];
        students[0]=student1;
        students[1]=student2;
        students[2]=student3;
       // Arrays.sort(students);
        List<Student> list=new ArrayList<>();
        list.add(student1);
        list.add(student2);
        list.add(student2);
        Collections.sort(list);
        System.out.println(Arrays.toString(students));
        System.out.println(list);
    }
}

1)Arrays.sort()也可以传入一个Comparator接口

谁调用compareTo方法,谁就是this

2)再去观察String类的源码,发现我们的String类也实现了Comparable接口重写了里面的compareTo方法

3)但是如果假设说此时如果说我们的需求发生了变化,此时我们根据年龄来进行比较,此时就需要在这个学生类中就需要进行修改内部的代码,这个时候就不好改了 

package com.example.demo;
import java.util.Arrays;
public class HelloWorld{
    public static void main(String[] args) {
        String[] strings={"a","aa","aaa","aaaa"};
        Arrays.sort(strings);
        System.out.println(Arrays.toString(strings));
    }
}
class Student implements Comparable<Student>{
    public String username;
    public int age;
    public String password;

    public Student(String username, int age, String password) {
        this.username = username;
        this.age = age;
        this.password = password;
    }

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                '}';
    }
}
public class UserController{
    public static void main(String[] args) {
        Student student1=new Student("A",19,"12345");
        Student student2=new Student("B",20,"115256");
        Student student3=new Student("C",21,"9090");
        Student student4=new Student("D",22,"8080");
        Student[] students=new Student[]{student1,student2,student3,student4};
        ArraySort(students);
        System.out.println(Arrays.toString(students));
    }

    private static void ArraySort(Comparable[] array) {
        for(int i=0;i<array.length-1;i++){
            boolean flag=false;
            for(int j=0;j<array.length-1-i;j++){
                if(array[i].compareTo(array[j])>0){
                    Comparable temp=array[i];
                    array[i]=array[j];
                    array[j]=temp;
                    flag=true;
                }
                if(flag==false){
                    return;
                }

            }
        }
    }

}

二)Comparator接口

1)定义一个新的类,让他继承Comparator接口,里面要有一个泛型参数,放比较的类型,之后在我们的main方法里面直接可以new一个比较器,里面的参数就是我们想要比较的类型

咱们的Comparator的接口的源码:

public interface Comparator<T>{
  int compare(T o1,T o2);
  boolean equals(Object obj)
}

2)Comparator是一个可比较接口,我们如果说想要控制某一个类的次序,但是这个类不支持排序,没有实现Comparable接口,那么我们在这个类外面创建一个类的比较器来进行排序,实现Comparator接口

3)实现Comparator的接口的实际应用:

4)Arrays.sort()里面有下面的给出的重载,可以用来排序自定义类型

Arrays.sort(T[] arr1,Comparator<? super T> c)
第一个参数传入数组,第二个参数传入一个Comparator接口

5)也可以对实现Comparable的类实现比较,comparable接口对类的侵入性比较强,但是使用起来非常灵活,用Comparator实现比较器,当某一个自定义对象需要进行比较的时候,把比较器和对象一起传入过去就大小了

  static class AgeComparator implements Comparator<Student>
    {
        public int compare(Student o1, Student o2) {
            return o1.age- o2.age;
        }
    }
    static class Student {
        public String name;
        public int age;
        public Double score;

        public Student(String name, int age, Double score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", score=" + score +
                    '}';
        }

    }
        public static void main(String[] args) {
            Student student1 = new Student("李佳伟", 15, 23.9);
            Student student2 = new Student("李佳鑫", 4, 89.9);
            Student student3 = new Student("周云刚", 89, 10.9);
            Student[] arr1 = {student1, student2, student3};
            Arrays.sort(arr1,new AgeComparator());
            System.out.println(Arrays.toString(arr1));
            //或者也可以这么进行比较
            AgeComparator ageComparator=new AgeComparator();
           if(ageComparator.compare(student1,student2)>0)
           {
               System.out.println(1);
           }

        }
三)Comparable(对内实现)和Comparator(对外实现)的区别

1)Comparable翻译成中文是比较的意思,而Comparator翻译成中文是比较器的意思

2)实现Comparable接口并重写compareTo方法就可以实现某一个类来进行排序了,支持Collections.sort()和Arrays.sort()的排序,如果说自定义对象没有实现Comparable接口,在Arrays.sort()方法的底层,都把数组每一个元素转化成了Compareable元素,或者传入一个比较器

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

4)Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

5)Comparable 对类的侵入性非常强, 一但投入使用便不方便再做修改,用起来比较简单,只要实现Comparable 接口的对象直接就成为一个可以比较的对象,需要重写comparTo方法,所以如果想要更换比较方式,就需要对comparTo “大动干戈”。

6)Comparator 对类的侵入性比较弱, 使用起来非常灵活,用Comparator实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 使用Comparator比较,如果想要更换比较方式,只需要在原来的基础上再增加一个比较器即可

package Demo;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class Task{
    public String name;
    public int age;
    public Task(String name,int age){
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Task{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class DemoKail{
    public static void main(String[] args) {
        List<Task> list=new ArrayList<>();
        Task task1=new Task("李佳伟",19);
        Task task2=new Task("李嘉欣",20);
        Task task3=new Task("及时雨",88);
        list.add(task1);
        list.add(task2);
        list.add(task3);
        list.sort(new Comparator<Task>() {
            @Override
            public int compare(Task o1, Task o2) {
                return o1.age-o2.age;
            }
        });
        System.out.println(list);
    }

}
default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);

Arrays.sort()和list.sort()都可以对Compareable和Compareator接口的类实现自定义比较

 public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }

上面是Collections.sort()

四)标准库常见的类实现Comparable接口或者是Compartor接口
1)String实现comparable接口,重写了compareTo方法

1)从前依次向后进行比较,字符不同,则返回两字符的ASCII 码的差值

2)如果两个字符相同,则返回两字符长度差值

 public int compareTo(String anotherString) {
        int len1 = value.length;//第一个字符串的长度
        int len2 = anotherString.value.length;//第二个字符串的长度
        int lim = Math.min(len1, len2);//取两个字符串长度的较小值
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {//进行遍历那个较小的字符串
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;//如果不相同返回ascil码的差值
            }
            k++;
        }
        return len1 - len2;//较小的字符串遍历完成直接返回他们的差值
    }
2)Integer实现compareable接口,重写了compareTo方法

两个包装类型要通过compareTo方法来进行比较的两个类中的value属性来进行比较

Integer装箱操作:在编译期将Integer a = 3;

这种格式的代码,会编译成Integer a = Integer.valueOf(3),这就是装箱操作。

Integer拆箱操作:在编译期将Integer转换成int类型,会调用int z = a.intValue()方法

拆箱操作在int类型与Integer类型进行==比较,此时Integer会进行拆箱操作

Integer a = new Integer(11);
Integer b = 11;
int c = 11;
System.out.println(a == c);
System.out.println(a == b);        

1)基本类型和包装类型进行==比较的时候,包装类型会自动进行拆箱操作,也就是包装类型会自动调用Integer.intValue方法,会转化成基本数据类型进行比较

public int intValue() {
        return value;
    }//这里面的intValue方法就是返回Integer中的value属性

当我们进行比较a和c的之的时候,a会自动拆箱成11,然后此时就是基本数据类型的比较了,基本数据类型比较的就是值,所以是true

2)当我们的包装类型和包装数据类型进行比较的时候,会将基本数据类型自动进行装箱

2.1)当我们的b和a进行比较的时候,会先将b进行装箱操作,底层会默认调用ValueOf方法

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

这个时候在-127到128之间返回的是一个缓存数组,但是此时a是在堆new出来的新对象,所以说他们的地址不相同,所以结果是false

   Integer a = 11;
   Integer b = 11;
   Integer c = 129;
   Integer d = 129;
   System.out.println(a == b);//此时是true
   System.out.println(c == d);//此时是false

 因为上述类型的比较都调用了valueOf来进行比较

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 下的线程接口是 POSIX 线程(pthread)库,它是一套标准的 API,定义了线程的创建、同步、通信等操作。下面绍一些常用的函数和操作: ### 线程创建 在 POSIX 线程库中,线程的创建使用 `pthread_create` 函数。它的原型如下: ```c int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); ``` 其中: - `thread`:指向线程标识符的指针。 - `attr`:指向线程属性的指针,如果为 `NULL`,表示使用默认属性。 - `start_routine`:线程的入口函数,它必须是一个指向函数的指针,且返回类型为 `void *`,接受一个 `void *` 类型的参数。 - `arg`:传递给线程入口函数的参数。 `pthread_create` 函数成功时返回 0,否则返回错误码。 ### 线程等待 线程等待使用 `pthread_join` 函数,它的原型如下: ```c int pthread_join(pthread_t thread, void **retval); ``` 其中: - `thread`:线程标识符。 - `retval`:指向线程返回值的指针,如果不需要返回值,可以传递 `NULL`。 `pthread_join` 函数会阻塞当前线程,直到指定的线程退出并返回。如果线程已经被分离,或者已经退出,`pthread_join` 函数会立即返回,并且不会修 `retval` 指向的值。`pthread_join` 函数成功时返回 0,否则返回错误码。 ### 线程分离 线程分离使用 `pthread_detach` 函数,它的原型如下: ```c int pthread_detach(pthread_t thread); ``` 其中: - `thread`:线程标识符。 `pthread_detach` 函数将指定的线程标记为分离状态,它的资源会在线程退出时自动被回收,无法再次被等待。如果一个线程已经被分离,再次调用 `pthread_detach` 函数会返回错误码。`pthread_detach` 函数成功时返回 0,否则返回错误码。 ### 线程取消 线程取消使用 `pthread_cancel` 函数,它的原型如下: ```c int pthread_cancel(pthread_t thread); ``` 其中: - `thread`:线程标识符。 `pthread_cancel` 函数向指定的线程发送一个取消请求,如果线程允许取消,它将会退出。线程可以通过设置取消状态和取消类型来控制取消的行为。`pthread_cancel` 函数成功时返回 0,否则返回错误码。 ### 线程同步 线程同步使用互斥锁、条件变量等机制来实现。这些机制可以通过 pthread 库提供的函数来使用,如 `pthread_mutex_init`、`pthread_mutex_lock`、`pthread_cond_init`、`pthread_cond_wait` 等等。这些函数的使用方法比较复杂,需要根据具体的应用场景来选择和使用。 以上是一些常用的 POSIX 线程库的函数和操作,使用时需要根据具体的业务需求进行选择和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值