比较器
1.1 数组操作类Arrays
Arrays 类一早就开始使用了,最早使用的是它的排序操作,但是现在打开Arrays类来观察下一下,有那些方法
(1)二分查找:public static int binarySearch(数据类型 a, 数据类型 key)
在进行此调用之前,数组必须按照sort(数据类型[])方法进行排序。如果没有排序,结果是未定义的。如果数组包含具有指定值的多个元素,则不能保证将找到哪个元素。
范例:二分查找
package day2;
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) throws Exception {
int date[] = {5,69,85,35,45,67,54,62,89,50,7,12,28};
Arrays.sort(date);
System.out.println(Arrays.binarySearch(date,67));//9
}
}
(2)数组比较:public static boolean equals(数据类型[] a,数据类型[] a2)
如果两个数组以相同的顺序包含相同的元素,则它们是相等的。另外,如果两个数组引用都是null,则它们被认为是相等的 。
范例:数组比较
package day2;
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) throws Exception {
int dateA[] = new int[]{1,2,3};
int dateB[] = new int[]{2,1,3};
int dateC[] = new int[]{1,2,3};
System.out.println(Arrays.equals(dateA,dateB));//false
System.out.println(Arrays.equals(dateA,dateC));//true
}
}
(3)数组填充:public static void fill(数据类型[] a,数据类型 val),将指定的 数据类型值分配给指定的数据类型 数组的每个元素。
(4)public static String toString(数据类型[] a)
返回指定数组的内容的字符串表示形式。 字符串表示由数组元素的列表组成,括在方括号( “[]” )中。 相邻的元素由字符", "分隔(逗号后跟一个空格)。 元素被转换为字符串由String.valueOf(int)。 返回"null"如果a是null。
范例:数组填充
package day2;
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) throws Exception {
int dateA[] = new int[]{1,2,3};
Arrays.fill(dateA,5);
System.out.println(Arrays.toString(dateA));
}
}
[5, 5, 5]
在Arrays类中几乎包含了所有可能使用到的数组的相关操作。
1.2 比较器 Comparable接口
在Arrays类中提供有一个方法:public static void sort(byte[] a),此方法可以直接针对于队形数组进行排序的操作;但是如果现在真的要进行对象数组的排序,并不是意味着直接调用此方法即可。如果要想进行对象数组的排序,需要解决数据的大小关系问题,但是对象无法区分大小关系,那么为了解决这样的一个问题,java会自动在排序的时候将所有的对象强制转换为Comparable接口对象,也就是数组的自动排序,那么对象所在的类一定要实现Comparable接口,这个接口定义如下:
public interface Comparable<T> {
public int compareTo(T o);
}
String 类中的compareTo()本身就是覆写了Comparable接口中的compareTo方法。而如果说下周需要进行排序,实际上只需要返回三个内容即可:0,-1,1
范例:对象数组排序
package day2;
import java.util.Arrays;
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名 :" + this.name + ",年龄:" + this.age + "\n";
}
/**
@Override
public int compareTo(Person p) {
return this.age - p.age;
}
**/
@Override
public int compareTo(Person p) {
if(this.age > p.age){//1升序,-1 降序
return 1;
}else if(this.age < p.age){
return -1;
}else {
return 0;
}
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
Person person [] = new Person[]{
new Person("张角",26),
new Person("王怡",18),
new Person("黎明",22)
};
Arrays.sort(person);
System.out.println(Arrays.toString(person));
}
}
[姓名 :王怡,年龄:18
, 姓名 :黎明,年龄:22
, 姓名 :张角,年龄:26
]
结论:只要是进行对象数组的排序,一定要使用Comparable接口完成。
1.3 实现二叉树算法(Binary Tree)
二叉树也好,链表也好,本质是一样的,目的就是为了保存多个数据,实现动态的对象数组。所有的数据结构都一定有一个前提:必须通过节点来进行数据的包裹,目的:确定先后顺序。那么现在也对Node进行修改,让其进行可以保存对象(Object,Comparable),但是现在每一个节点上要保留有两个子节点:左子树、右子树
保存原则:比根节点小的数据放在左子树,比根节点大于等于的数据保存在左子树。
最后按照中序遍历(左-根-右)的方式可以取得内容,所有数据的排序后的结果。
范例:实现二叉树
package day2;
import java.util.Arrays;
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名 :" + this.name + ",年龄:" + this.age + "\n";
}
@Override
public int compareTo(Person p) {
return this.age - p.age;
}
}
class MyBinaryTree{//二叉树的实现类
private class Node{//数据结构中必须有Node类,负责保存数据及节点的关系匹配
@SuppressWarnings("rawtypes")
private Comparable data;
private Node left;//左子树,保存比根节点小的内容
private Node right;//右子树,保存比根节点大或等于的内容
@SuppressWarnings({"rawtypes","unused"})
public Node(Comparable data){
this.data = data;
}
public void addNode(Node newNode){
if(this.data.compareTo(newNode.data) > 0){ //保存在左边
if(this.left == null){
this.left = newNode;
}else {
this.left.addNode(newNode);
}
}else {
if(this.right == null){
this.right = newNode;
}else {
this.right.addNode(newNode);
}
}
}
public void toArrayNode(){
if(this.left != null){//有左节点
this.left.toArrayNode();
}
MyBinaryTree.this.retData[MyBinaryTree.this.foot++] = this.data;
if(this.right != null){//有右节点
this.right.toArrayNode();
}
}
}
/********************* 编写BinaryTree 操作****************************/
private Node root;//必须保留着根节点
private int count = 0 ;//保存节点个数
private Object[] retData;
private int foot = 0;
public void add(Object obj){//数据的追加
Comparable data = (Comparable)obj;
Node newNode = new Node(data);//将数据包装在Node节点中
if(this.root == null){//保存根节点
this.root = newNode;
}else {
this.root.addNode(newNode);
}
this.count++;
}
public Object[] toArray(){
if(this.count > 0){
this.foot = 0;
this.retData = new Object[this.count];
this.root.toArrayNode();
return this.retData;
}else {
return null;
}
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
MyBinaryTree mbt = new MyBinaryTree();
mbt.add( new Person("张角",26));
mbt.add( new Person("王怡",18));
mbt.add( new Person("黎明",22));
mbt.add( new Person("李思",15));
System.out.println(Arrays.toString(mbt.toArray()));
}
}
[ 姓名 :李思,年龄:15
, 姓名 :王怡,年龄:18
, 姓名 :黎明,年龄:22
, 姓名 :张角,年龄:26
]
1.4 Comparator 比较器
通过Comparable的观察可以发现,如果一个类的对象想要进行对象数组排序,那么这个类在定义的时候就必须明确的实现Comparable接口,如果出现一个类原本定义完成了,原本是没有排序要求的,可是后期需要追加排序,并且这个类已经不能够修改了。那么在这种情况下,就可以利用java.util.Comparator接口,此接口定义如下:
@FunctionalInterface
public interface Comparator<T> {
public int compare(T o1, T o2);
public boolean equals(Object obj);
}
如果要想继续使用Arrays实现排序操作,那么就必须观察新的排序方法:
排序:public static void sort(T[] a,int fromIndex,int toIndex, Comparator<? super T> c)
范例:定义一个单独的Person类(不允许Person类发生改变)
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名 :" + this.name + ",年龄:" + this.age + "\n";
}
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;
}
}
范例:实现单独的比较器
package day2;
import java.util.Arrays;
import java.util.Comparator;
class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
Person person [] = new Person[]{
new Person("张角",26),
new Person("王怡",18),
new Person("黎明",22)
};
Arrays.sort(person,new PersonComparator());//编写排序
System.out.println(Arrays.toString(person));
}
}
[姓名 :王怡,年龄:18
, 姓名 :黎明,年龄:22
, 姓名 :张角,年龄:26
]
面试题:请解释两种比较器的区别
(1)在进行对象数组排序的过程中需要使用到比较器,比较器有两个:Comparable、Comparator
(2)java.lang.Comparable:是在类定义的的时候默认实现好的接口,里面提供有一个compateTo()方法用于大小比较;
(3)java.util.Comparator需要单独定义一个排序的比较规则类,里面有两个方法:compare()、equals()。