Java数组排序

时间:2025-03-27 13:36:01

1. 基本类型排序

1.1 升序

基本类型可直接调用()进行排序,默认升序排列:

public class Test {
    public static void sort() {
        int[] nums = new int[]{4, 3, 2, 6, 4, 23, 18};
        System.out.println("排序前:" + Arrays.toString(nums));
        Arrays.sort(nums);
        System.out.println("排序后:" + Arrays.toString(nums));
    }

    public static void main(String[] args) {
        sort();
    }
}

执行结果:

排序前:[4, 3, 2, 6, 4, 23, 18]
排序后:[2, 3, 4, 4, 6, 18, 23]

1.2 降序

如果需要进行降序排列,则需要自定义比较器Comparator,但Comparator仅支持包装类和自定义类,不支持基本数据类型,如果对基本类型进行降序排列,可以对数组进行升序排列后反转:

public class Test {
    public static void sort() {
        int[] nums = new int[]{4, 3, 2, 6, 4, 23, 18};
        System.out.println("排序前:" + Arrays.toString(nums));
        Arrays.sort(nums);
        reverse(nums);
        System.out.println("排序后:" + Arrays.toString(nums));
    }

    public static void reverse(int[] nums) {
        for (int left = 0, right = nums.length - 1; left < right; left++, right--) {
            // swap the values at the left and right indices
            int temp = nums[left];
            nums[left]  = nums[right];
            nums[right] = temp;
        }
    }

    public static void main(String[] args) {
        sort();
    }
}

执行结果:

排序前:[4, 3, 2, 6, 4, 23, 18]
排序后:[23, 18, 6, 4, 4, 3, 2]

Java包装类,如Integer,需要通过自定义Comparator类来自定义排序顺序:

public class Test {
    public static void sort() {
        Integer[] nums = new Integer[]{4, 3, 2, 6, 4, 23, 18};
        System.out.println("排序前:" + Arrays.toString(nums));

        // 1. 自定义比较器Compartor
        Arrays.sort(nums, new IntegerComparator());
        System.out.println("排序后:" + Arrays.toString(nums));

        // 2. 匿名类
        Arrays.sort(nums, new Comparator<Integer>() {
            @Override
            public int compare(Integer n1, Integer n2) {
                return n2 - n1;
            }
        });
        System.out.println("排序后:" + Arrays.toString(nums));

        // 3. lambda表达式
        Arrays.sort(nums, (n1, n2) -> n2 - n1);
        System.out.println("排序后:" + Arrays.toString(nums));
    }

    public static void main(String[] args) {
        sort();
    }
}

class IntegerComparator implements Comparator<Integer> {
    @Override
    public int compare(Integer n1, Integer n2) {
        return n2 - n1;
    }
}

执行结果:

排序前:[4, 3, 2, 6, 4, 23, 18]
排序后:[23, 18, 6, 4, 4, 3, 2]
排序后:[23, 18, 6, 4, 4, 3, 2]
排序后:[23, 18, 6, 4, 4, 3, 2]

Comparator的详细介绍见后面章节。

2. 自定义类型排序

2.1 Java比较器 - Comparable

Comparable 是排序接口,若一个类实现了 Comparable 接口,就意味着该类“支持排序”或者“具有比较能力”。如,当前有一个描述小狗的类Dog,具有名字和年龄两个属性,要求可以根据小狗的年龄大小进行排序:

public class Dog implements Comparable<Dog> {
    private String name;

    private int age;

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

    @Override
    public String toString() {
        return "Dog{name: " + this.name + ", age: " + this.age + "}";
    }

	// 重写compareTo方法
    @Override
    public int compareTo(Dog dog) {
        if (this.age > dog.age) {
            return 1;
        } else if (this.age < dog.age) {
            return -1;
        }
        return 0;
    }
}

compareTo方法用来比较两个实例的大小,比较器根据该方法返回值进行排序:

  • 返回正数,表示当前实例比传入的实例大
  • 返回复数,表示当前实例比传入的实例小
  • 返回0,表示两者相等

因此上述代码中的compareTo()可以简写为:

public int compareTo(Dog dog) {
    return this.age - dog.age;
}

构造一个Dog数组,进行排序:

public class Test {
    public static void sort() {
        Dog dog1 = new Dog("AAA", 3);
        Dog dog2 = new Dog("BBB", 2);
        Dog dog3 = new Dog("CCC", 4);
        Dog dog4 = new Dog("DDD", 1);
        Dog[] dogs = new Dog[]{dog1, dog2, dog3, dog4};
        System.out.println("排序前:" + Arrays.toString(dogs));

        Arrays.sort(dogs);
        System.out.println("排序后:" + Arrays.toString(dogs));
    }

    public static void main(String[] args) {
        sort();
    }
}

执行结果:

排序前:[Dog{name: AAA, age: 3}, Dog{name: BBB, age: 2}, Dog{name: CCC, age: 4}, Dog{name: DDD, age: 1}]
排序后:[Dog{name: DDD, age: 1}, Dog{name: BBB, age: 2}, Dog{name: AAA, age: 3}, Dog{name: CCC, age: 4}]

若要实现按照年龄降序排列,compareTo可定义为:

public int compareTo(Dog dog) {
	return dog.age - this.age;
}

2.2 Java比较器 - Comparator

Comparator是定义在类之外的比较器,该类本身并不支持排序,而只是定义一种排序规则。当不希望改变原有类,或者原有类提供的比较器不支持当前需求时,可以考虑外部定义Comparator实现类。

现在仍然有一个小狗的类,但是没有实现Comparable接口:

public class Dog {
    private String name;

    private int age;

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

    @Override
    public String toString() {
        return "Dog{name: " + this.name + ", age: " + this.age + "}";
    }
	public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

接下来实现Comparator类,实现其compare方法:

public class Test {
    public static void sort() {
        Dog dog1 = new Dog("AAA", 3);
        Dog dog2 = new Dog("BBB", 2);
        Dog dog3 = new Dog("CCC", 4);
        Dog dog4 = new Dog("DDD", 1);
        Dog[] dogs = new Dog[]{dog1, dog2, dog3, dog4};
        System.out.println("排序前:" + Arrays.toString(dogs));

        Arrays.sort(dogs, new DogComparator());
        System.out.println("排序后:" + Arrays.toString(dogs));
    }

    public static void main(String[] args) {
        sort();
    }
}

class DogComparator implements Comparator<Dog> {
    @Override
    public int compare(Dog d1, Dog d2) {
        return d1.getAge() - d2.getAge();
    }
}

执行结果:

排序前:[Dog{name: AAA, age: 3}, Dog{name: BBB, age: 2}, Dog{name: CCC, age: 4}, Dog{name: DDD, age: 1}]
排序后:[Dog{name: DDD, age: 1}, Dog{name: BBB, age: 2}, Dog{name: AAA, age: 3}, Dog{name: CCC, age: 4}]

compare方法与compareTo方法类似,都是根据返回值进行排序。
为了方便,也可以采用匿名类或者lambda的方式:

Arrays.sort(dogs, new Comparator<Dog>() {
    @Override
    public int compare(Dog d1, Dog d2) {
        return d1.getAge() - d2.getAge();
    }
});

// 或者
Arrays.sort(dogs, (d1, d2) -> d1.getAge() - d2.getAge());

2.3 Comparator 和 Comparable 区别

  • 内部比较器 Comparable 是排序接口,只包含一个函数 compareTo();若一个类实现了 Comparable 接口,就意味着 “该类支持排序”,它可以直接通过 () 或 () 进行排序。
  • 外部比较器 Comparator 是比较器接口,单独实现一个比较器,不需要对原来的类进行结构上的变化,属于无侵入式的;一个类实现了 Comparator 接口,那么它就是一个 “比较器”。其它的类,可以根据该比较器去排序。