最全的Java中Arrays.sort()与Collections.sort()底层原理和字符串比较排序分析

 

如果我们直接调用Arrays.sort()与Collections.sort()排序自然是升序排序出来,但是我们经常需要自己去定义些排序的规则,由于我们对底层原理不是很清楚导致我们无法改写排序规则。同时假如给你一个字符串怎了比较排序或是自定义排序?

针对上面问题所以想全面总结下怎么自如的运用Arrays.sort()与Collections.sort()做个分析。

首先我们从三个方面来解析:

  1. 数组排序 Arrays.sort()与集合Collections.sort()方法

  2. Compareable接口和Compartor接口对比分析

  3. 分析自定义字符串比较排序方法

1.Arrays.sort()与Collections.sort()排序

一般我们在没有特殊要求时我们可以直接调用上面排序方法排序,底层默认的升序排列,就可以得到我们想要的结果。

Arrays.sort()可以对数组,字符串等排序:

package leetcode;

import java.util.Arrays;

/**
 * @author 江河
 * @date 2020-02-10 11:50
 */
public class sort {
  public static void main(String[] args) {
    int[] num = new int[]{3,2,4,1,5};
    Arrays.sort(num);
    for(int i=0;i<num.length;i++) {
      System.out.print(num[i]+" ");
    }
  }
}

Collections.sort()是对list集合排序,list也可以放数字、字符串:

package leetcode;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @author 江河
 * @date 2020-02-10 11:50
 */
public class sort {
  public static void main(String[] args) {
    ArrayList<Integer> list  = new ArrayList<>();
    list.add(3);
    list.add(2);
    list.add(1);
    Collections.sort(list);
    System.out.print(list);
  }
}

2.Compareable和Compartor接口分析

其实所谓的sort方法排序底层都是基于这两种排序,故如果我们需要设计成我们自己所想要的排序就需要了解底层排序原理才能设计。对自定义对象数组排序,需要引入“比较器”,的概念。
Compareable和Compartor接口就是比较器抽象接口,通过实现类,重写接口方法来进行对象比较。

2.1 Compareable接口

当使用sort(Objetc[] a)来进行对象的自然排序,该对象必需实现Compareable接口重写compareableTo方法,并一般在此方法中定义这3种返回值(正,零,负)来进行排序标准的确认,一般默认下面值来表示。

  • return 1 时,按照从小到大升序
  • return 0 时,原位置不动
  • return-1 时,按照从在大到小降序

而让对象继成Compareable接口的方式,称为内部比较器。

public class Student implements Comparable {

	String name;
	Integer age;

	public Student(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public Student() {
		super();
	}

	public String getName() {
		return name;
	}

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

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub

		if (o instanceof Student) {
			Student s = (Student) o;
			if (this.age > s.age) {
				return 1;
			} else if (this.age == s.age) {
				return 0;
			} else {
				return -1;
			}
		}
		return 0;

	}

以上代码只是演示并没有具体实现过,实现接口实现方法。 上面是实现升序排列,如果要实现降序只需要把1与-1互换位置。

 2.2 Compartor接口

2.2.1 一般在创建对象或是一个基本类时如下:

(1)先建一个基本属性类 

public class Student {
    //创建两个基本属性
    String name="";
    int age=0;
   
    //从写构造方法用来传递数据
    public Student(String name, int age) {
       super();
       this.name = name;
       this.age = age;
    }
    //从写toString方法,方便显示
    @Override
    public String toString() {
       return name + "  " + age ;
    }
   
    //基本属性的get和set方法
    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;
    }
   
}

(2)创建按照姓名升序排列的实现类 

import java.util.Comparator;
       //按照名字的升序排列    实现接口       泛型是自定义类,里面有要排序的内容   
public class NameSort implements Comparator{
    @Override         //两个参数是泛型的对象
    public int compare(Student o1, Student o2) {
                  //按照姓名的升序排列,前面加个负号就按照降序排列
       return o1.getName().compareTo(o2.getName());
    }
}

2.2.2 直接自己定义,这个一般在刷题时经常这样用,

Arrays.sort(num,new Comparator<String>(){ //传进来的数组或是字符串以及集合list
            @Override
            public int compare(String o1,String o2){
                return o1.compareTo(o2);//升
                //return o2.compareTo(o1);//降

            }
        });

 Java 中PriorityQueue优先级队列就是利用这原理

3.分析自定义字符串比较排序方法

    源码底层说的比较抽象,大体总结白话说出来,String 是字符串,它的比较用compareTo方法,它从第一位开始往后比较, 如果遇到不同的字符,则马上返回这两个字符的ASCII值差值.返回值是int类型。

1.当两个比较的字符串是英文字母相同且长度不等时,返回的是串的长度之差

String a = "helloworld"

String b = "hello"

==> a.length() - b.length() = 5

2.如果这两个字符串不同,那么它们要么在某个索引处的字符不同(该索引对二者均为有效索引),要么长度不同,或者同时具备这两种情况返回的是第一个不同的字母ASCII值差值,比较形式是转化成char数组一个个比较。

String a="as";
String b="b";

字母ASCII值差值:num=-1;

String a="aa";
String b="ab";

第一个通往后移,不同比较返回字母ASCII值差值:num=-1;

String a="ab";
String b="ba";

返回第一个比较的字母ASCII值差值:num=-1; 

Arrays.sort(str,new Comparator<String>(){
            @Override
            public int compare(String o1,String o2){
                return c1.compareTo(c2);
            }
        });
​​​​​​​

运用:

题目描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

import java.util.*;

public class Solution {
    public String PrintMinNumber(int [] numbers) {
        if(numbers.length==0) {
            return "";
        }
        int len = numbers.length;
        String[] str = new String[len];
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<len;i++) {
            str[i] = String.valueOf(numbers[i]);
        }
        Arrays.sort(str,new Comparator<String>(){
            @Override
            public int compare(String o1,String o2){
                String c1 = o1 + o2;
                String c2 = o2 + o1;
                return c1.compareTo(c2);
            }
        });
        for(int i=0;i<len;i++) {
            sb.append(str[i]);
        }
        return sb.toString();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值