【Java】自定义排序

3,690 阅读4分钟

前言

本文介绍一个自定义排序和常见的排序API

比较器

  • 通过实现Comparator接口中的compare(T o1, T o2)方法来实现自定义排序

    方法一:

    class MyComparator implements Comparator<Integer> {
    
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    }
    Collections.sort(list, new MyComparator());
    

    方法二

    Collections.sort(list, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    });
    
    • 返回值<0:交换o1和o2的位置
    • 返回值=0:不交换位置,不排序
    • 返回值>0:不交换o1和o2的位置
  • 类实现Comparable接口,实现compareTo(T o)方法。

    class Student implements Comparable<Student> {
    
        int sum;
        
        @Override
        public int compareTo(Student o) {
            return this.sum - o.sum;
        }
    }
    

一、普通数组 int[]

1、Arrays.sort()类

  • Arrays.sort(int[] arr) 按照数字从小到大排序

    import java.util.Arrays;
    import java.util.Scanner;
    
    /**
     * @author yanshuang
     * @date 2021/11/14 1:03 下午
     */
    public class SortTest {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            int[] arr = new int[n]; // 数组大小可以定义
            System.out.print("排序前:");
            for(int i = 0;i < n;i ++) {
                arr[i] = sc.nextInt();
            }
            Arrays.sort(arr,0,n);
            System.out.print("排序后:");
            for(int i = 0;i < n;i ++) {
                System.out.print(arr[i] + " ");
            }
        }
    }
    
    

    运行结果:

    5
    排序前:1 7 3 5 2
    排序后:1 2 3 5 7
    

    当前数组的大小和输入的限定是一样大小,如果不一样

    int[] arr = new int[1000];
    
    5
    排序前:1 9 5 3 4
    排序后:0 0 0 0 0 
    

    注意Array.sort的后两个参数,如果你数组开的大小比你要排序的数组大小大,那么数组中除了你输入的数字外,其他都是0

  • Arrays.sort(int[] a, int fromIndex, int toIndex)按照指定区间排序数组

    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Scanner;
    
    /**
     * @author yanshuang
     * @date 2021/11/14 1:03 下午
     */
    public class SortTest {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            int[] arr = new int[n]; // 数组大小可以定义
            System.out.print("排序前:");
            for(int i = 0;i < n;i ++) {
                arr[i] = sc.nextInt();
            }
            Arrays.sort(arr, 2,4);
            System.out.print("排序后:");
            for(int i = 0;i < n;i ++) {
                System.out.print(arr[i] + " ");
            }
        }
    }
    
    

    运行结果

    5
    排序前:1 9 5 3 4
    排序后:1 9 3 5 4 
    

    注意Array.sort的后两个参数,如果你数组开的大小比你要排序的数组大小大,那么数组中除了你输入的数字外,其他都是0

    建议使用这种排序方法,上面有解释

2、Arrays.parallelSort()

用法大致和Array.sort()差不多

  • Arrays.parallelSort(T[] a)
import java.util.Arrays;
import java.util.Scanner;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n]; // 数组大小可以定义
        System.out.print("排序前:");
        for(int i = 0;i < n;i ++) {
            arr[i] = sc.nextInt();
        }
        Arrays.parallelSort(arr);
        System.out.print("排序后:");
        for(int i = 0;i < n;i ++) {
            System.out.print(arr[i] + " ");
        }
    }
}

运行结果

5
排序前:1 9 5 3 4
排序后:1 3 4 5 9 
  • Arrays.parallelSort(T[] a, int fromIndex, int toIndex):对指定对象升序排列的数组的指定范围内,根据natural ordering的元素。

    和Arrays.sort(int[] a, int fromIndex, int toIndex)差不多

⚠️注意:这种方法只能进行生序排序,不能进行自定义排序

二、包装类数组 Integer[]

大多数用于自定义比较器,这里主要讲降序。

注意下面

1、 Arrays.parallelSort()

  • Arrays.parallelSort(T[] a, Comparator<? super T> cmp):根据指定的比较器引发的顺序对指定的对象数组进行排序。

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.Scanner;
    
    /**
     * @author yanshuang
     * @date 2021/11/14 1:03 下午
     */
    public class SortTest {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            Integer[] arr = new Integer[n]; // 数组大小可以定义
            System.out.print("排序前:");
            for(int i = 0;i < n;i ++) {
                arr[i] = sc.nextInt();
            }
            Arrays.parallelSort(arr, new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
            System.out.print("排序后:");
            for(int i = 0;i < n;i ++) {
                System.out.print(arr[i] + " ");
            }
        }
    }
    

    运行结果

    5
    排序前:1 9 5 3 4
    排序后:9 5 4 3 1
    
  • Arrays.parallelSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> cmp):根据指定的比较器引发的顺序对指定的对象数组的指定范围进行排序。

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.Scanner;
    
    /**
     * @author yanshuang
     * @date 2021/11/14 1:03 下午
     */
    public class SortTest {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            Integer[] arr = new Integer[n]; // 数组大小可以定义
            System.out.print("排序前:");
            for(int i = 0;i < n;i ++) {
                arr[i] = sc.nextInt();
            }
            Arrays.parallelSort(arr,2,4 , new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
            System.out.print("排序后:");
            for(int i = 0;i < n;i ++) {
                System.out.print(arr[i] + " ");
            }
        }
    }
    

    运行结果

    5
    排序前:1 9 3 4 5
    排序后:1 9 4 3 5 
    

2、Arrays.sort()

  • Collections.reverseOrder()
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Integer[] arr = new Integer[n]; // 数组大小可以定义
        System.out.print("排序前:");
        for(int i = 0;i < n;i ++) {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr, Collections.reverseOrder());
        System.out.print("排序后:");
        for(int i = 0;i < n;i ++) {
            System.out.print(arr[i] + " ");
        }
    }
}

运行结果

5
排序前:1 9 5 3 4
排序后:9 5 4 3 1 
  • Arrays.sort(T[] a, Comparator<? super T> c)

根据指定的比较器引发的顺序对指定的对象数组进行排序

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Integer[] arr = new Integer[n]; // 数组大小可以定义
        System.out.print("排序前:");
        for(int i = 0;i < n;i ++) {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.print("排序后:");
        for(int i = 0;i < n;i ++) {
            System.out.print(arr[i] + " ");
        }
    }
}

运行结果

5
排序前:1 2 3 4 5
排序后:5 4 3 2 1 

3、集合排序

import java.util.*;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> list = new ArrayList<>();
        System.out.println("排序前");
        for(int i = 0;i < n;i ++) {
            list.add(sc.nextInt());
        }
        Collections.sort(list);
        System.out.println("排序后");
        for(int i =0;i < n;i ++) {
            System.out.print(list.get(i) + " ");
        }
    }
}

运行结果

5
排序前
1 6 2 3 4
排序后
1 2 3 4 6 

自定义排序可以添加比较器

三、对象数组

对于对象数组的自定义排序则有两种方式:

  • 类实现Comparable接口,实现compareTo(T o)方法,然后调用Arrays.sort(Object o)方法或sort(Object[] a, int fromIndex, int toIndex)方法
  • 使用与包装类型数组相同的方法,实现Comparator接口中的compare(T o1, T o2)方法来实现自定义排序

1、实现 Comparable 接口

先定义一个Student类实现Comparable接口

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Student[] students = new Student[n];
        System.out.println("排序前:");
        for(int i = 0;i < n;i ++) {
            Integer id = sc.nextInt();
            int sum = sc.nextInt();
            students[i] = new Student(id, sum);
        }
        System.out.println("排序后:");
        Arrays.sort(students);
        for(int i = 0;i < n;i ++) {
            System.out.println(students[i].id + " " + students[i].sum);
        }
    }


}

class Student implements Comparable<Student>{
    int id;
    int sum;

    public Student(int id, int sum) {
        this.id = id;
        this.sum = sum;
    }

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

运行结果

3
排序前:
1 1000
2 2000
3 1500
排序后:
1 1000
3 1500
2 2000

实现排序的关键方法为compareTo(Employee e)方法,那么它的返回值也决定了排序的结果。

2、实现 Comparator 接口中的 compare(T o1, T o2) 方法

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Student[] students = new Student[n];
        System.out.println("排序前:");
        for(int i = 0;i < n;i ++) {
            Integer id = sc.nextInt();
            int sum = sc.nextInt();
            students[i] = new Student(id, sum);
        }
        System.out.println("排序后:");
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.sum - o2.sum;
            }
        });
        for(int i = 0;i < n;i ++) {
            System.out.println(students[i].id + " " + students[i].sum);
        }
    }


}

class Student {
    int id;
    int sum;

    public Student(int id, int sum) {
        this.id = id;
        this.sum = sum;
    }
}

运行结果

3
排序前:
1 1000
2 2000
3 1500
排序后:
1 1000
3 1500
2 2000

2、集合排序

使用集合工具类Collections中的sort()方法 可以直接调用静态方法Collections.sort(List list)或者Collections.sort(List list, Comparator<? super T>对List进行排序。前者是升序排序,后者是自定义排序规则。

import java.util.*;

/**
 * @author yanshuang
 * @date 2021/11/14 1:03 下午
 */
public class SortTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        List<Student> list = new ArrayList<>();
        System.out.println("排序前:");
        for(int i = 0;i < n;i ++) {
            Integer id = sc.nextInt();
            int sum = sc.nextInt();
            Student student = new Student(id, sum);
            list.add(student);
        }
        System.out.println("排序后:");
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.sum - o2.sum;
            }
        });
        for(int i = 0;i < n;i ++) {
            System.out.println(list.get(i).id + " " + list.get(i).sum);
        }
    }


}

class Student {
    int id;
    int sum;

    public Student(int id, int sum) {
        this.id = id;
        this.sum = sum;
    }
}

运行结果

3
排序前:
1 1000
2 2000
3 1500
排序后:
1 1000
3 1500
2 2000