JavaSE02_Day02(下)-List的sort方法排序(整数、字符串)、Comparable、Comparator

List排序

1.1 sort方法实现整数排序

       之前在第一阶段学习过数组,并且通过调用数组工具类Arrays提供的sort()方法,可以进行对数组中的元素进行排序。当前所学习集合也提供了可以进行对集合中的元素进行遍历的API方法,在这里使用的是集合的工具类Collections提供的sort()方法,这个方法是一个静态方法(类方法),需要通过Collections类名进行调用排序

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

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 
 /**
  * 使用Collections集合工具类所提供的sort方法对集合进行排序,
  * sort方法可以对集合中的整数元素内容进行从小到大排序(升序)
  * @author cjn
  *
  */
 public class Collection_sort {
 
     public static void main(String[] args) {
         //1.创建集合对象
         List<Integer> list = new ArrayList<Integer>();
         
         //调用产生随机数的API:Random
         Random random = new Random();

         //2.向集合中添加元素内容
         for (int i = 0; i < 10; i++) {
             //通过循环每次生成不同的随机数
             int num = random.nextInt(50);
             list.add(num);    
        }
         System.out.println("集合对象:" + list);
         
         //3.对集合中的元素进行升序排列
         Collections.sort(list);//注意:此处是Collections而不是Collection
         System.out.println("排序后的集合对象:" + list);
 
    }
 
 }

随机一次的测试结果:

 集合对象:[8, 41, 18, 46, 36, 22, 6, 36, 20, 37]
 排序后的集合对象:[6, 8, 18, 20, 22, 36, 36, 37, 41, 46]

1.2 sort方法实现英文字符串排序

       如果要对字符串进行排序,实际是按照字符Unicode编码进行排序的。

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 /**
  * 使用集合工具类Collections提供的sort方法对集合中字符串内容进行排序
  * @author cjn
  *
  */
 public class Collection_sort02 {
 
     public static void main(String[] args) {
         //1.创建集合对象
         List<String> list = new ArrayList<String>();
         
         //2.向集合中添加元素内容
         /*
          1、星期一Monday英 [ˈmʌndeɪ; ˈmʌndi] 美 [ˈmʌnde; ˈmʌndɪ]
          2、星期二Tuesday英 ['tjuːzdeɪ; -dɪ] 美 [ˈtuzdɪ;-de]
          3、星期三Wednesday英 [ˈwenzdɪ] 美 [ˈwɛnzdɪ]
          4、星期四Thursday英 ['θɜːzdeɪ; -dɪ] 美 [ˈθɝzde; ˈθɝzdɪ]
          5、星期五Friday英 [ˈfraɪdeɪ]
          6、星期六Saturday英 [ˈsætədɪ; -deɪ] 美 [sætɚdɪ; -de]
          7、星期日Sunday英 [ˈsʌndeɪ; ˈsʌndi] 美 [ˈsʌnde; ˈsʌndi]
          abcdefghijklmnopqrstuvwxyz
          */
         list.add("Monday");
         list.add("Tuesday");
         list.add("Wednesday");
         list.add("Thursday");
         list.add("Friday");
         list.add("Saturday");
         list.add("Sunday");
         System.out.println("集合对象:" + list);
         
         //3.对集合中的元素内容进行排序
         Collections.sort(list);
         System.out.println("排序后的集合对象:" + list);
    }
 
 }

测试结果:

 集合对象:[Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
 排序后的集合对象:[Friday, Monday, Saturday, Sunday, Thursday, Tuesday, Wednesday]

结果分析:按照Unicode编码顺序进行比较,先比较第一个字母,若不同,按照a-zA-Z顺序从小到到排序;若相同,再比较第二个字母,按照同样的规则进行比较。

1.3 sort方法实现中文字符串排序

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 /**
  * 使用集合工具类型中sort方法对字符串中的中文内容进行排序
  * @author cjn
  *
  */
 public class Collection_sort03 {
 
     public static void main(String[] args) {
         //1.创建集合对象
         List<String> list = new ArrayList<String>();
         
         //2.向集合对象中添加元素内容
         list.add("陈龙");
         list.add("孟滕滕");
         list.add("苍老师");
         list.add("包老师");
         list.add("张鹏老师");
         System.out.println("集合对象:" + list);
         
         //3.对集合中的元素进行排序
         Collections.sort(list);
         System.out.println("排序后的集合对象:" + list);
         /*
          * 注意事项:对集合中的字符串元素进行排序,尤其是
          * 集合中的元素都为中文的情况下,查看排序规律是比较复杂的,
          * 本质是通过Unicode编码进行排序,在实际应用中,一般情况
          * 会根据当前公司项目的实际业务,制定一套排序标准进行排序
          */
    }
 
 }

测试结果:

 集合对象:[陈龙, 孟滕滕, 苍老师, 包老师, 张鹏老师]
 排序后的集合对象:[包老师, 孟滕滕, 张鹏老师, 苍老师, 陈龙]

1.4 Comparable(不推荐)

       通过查看源码发现,当点击进入到集合中的源码,查看集合类的后方并没有实现Comparable接口,而集合中的元素内容所对应的类型,进行查看源码时可以看到,这些类的后方使用implements实现Comparable接口,正是因为集合中这些元素类型实现了该接口,所以咱们才可以对集合中的元素进行排序。并且咱们不是对集合进行排序,而是对集合中的元素进行排序,所以集合类的后方没有进行实现Comparable接口。

集合类:没有实现Comparable接口

  public interface Collection<E> extends Iterable<E> 

  public interface List<E> extends Collection<E> 

  public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

元素类型:实现了Comparable接口

  public final class Integer extends Number implements Comparable<Integer> 

  public final class Double extends Number implements Comparable<Double> 

  public final class Float extends Number implements Comparable<Float>

注意事项

       在工作中,使用该方案的概率并不大,原因是该方法会造成代码的耦合度较高,不利于后期的维护,也就是需要将排序的规则进行嵌入到当前类中实现排序,所以不推荐。

Point.java

 package cn.tedu.collection_two;
 /**
  * 使用点对象进行排序使用
  * @author cjn
  *
  */
 public class Point implements Comparable<Point>{
     //添加点的x和y坐标
     private int x;
     private int y;
     
     /**
      * 构造器
      */
     public Point () {}
     public Point (int x,int y) {
         this.x = x;
         this.y = y;
    }
     
     /**
      * set和get方法
      */
     public int getX() {
         return x;
    }
     public void setX(int x) {
         this.x = x;
    }
     public int getY() {
         return y;
    }
     public void setY(int y) {
         this.y = y;
    }
     
     /**
      * hashCode和equals方法
      */
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + x;
         result = prime * result + y;
         return result;
    }
     @Override
     public boolean equals(Object obj) {
         if (this == obj)
             return true;
         if (obj == null)
             return false;
         if (getClass() != obj.getClass())
             return false;
         Point other = (Point) obj;
         if (x != other.x)
             return false;
         if (y != other.y)
             return false;
         return true;
    }
     
     /**
      * toString方法
      */
     @Override
     public String toString() {
         return "Point [x=" + x + ", y=" + y + "]";
    }
     
     /**
      * compareTo这个方法是Comparable接口中所提供的抽象方法,
      * 实现该方法可以进行自定义的比较规则。
      *
      * 比较两个点的大小:
      * 根据两个点的x和y的坐标值,求这个点距离原点的距离,
      * 距离大的认为这个就是大点,距离短的就认为这个点是小点。
      *
      * 当返回值>0 证明当前对象>参数对象
      * 当返回值<0 证明当前对象<参数对象
      * 当返回值=0 证明当前对象等于参数对象
      */
     @Override
     public int compareTo(Point o) {
         //点一距离原点的长度
         int len = (int)Math.sqrt(this.x * this.x + this.y * this.y);
         //点二距离原点的长度
         int len2 = (int)Math.sqrt(o.x * o.x + o.y * o.y);
         return len - len2;
    }
     
 }

 

自定义比较规则测试类:Collection_sort04.java

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 /**
  * 自定义比较测试
  * @author cjn
  *
  */
 public class Collection_sort04 {
 
     public static void main(String[] args) {
         List<Point> list = new ArrayList<Point>();
         list.add(new Point(-2, 5));
         list.add(new Point(1, 1));
         list.add(new Point(10, -6));
         list.add(new Point(-2, -2));
         list.add(new Point(0, 3));
         System.out.println(list);
         
         //上面的Point类中定义了比较规则,此处进行排序时会调动比较规则
         Collections.sort(list);
         System.out.println("排序后的集合:" + list);
 
    }
 
 }

测试结果:

 [Point [x=-2, y=5], Point [x=1, y=1], Point [x=10, y=-6], Point [x=-2, y=-2], Point [x=0, y=3]]
 排序后的集合:[Point [x=1, y=1], Point [x=-2, y=-2], Point [x=0, y=3], Point [x=-2, y=5], Point [x=10, y=-6]]

1.5 Comparator比较器(推荐)

int compare(T o1, T o2);

自定义比较器类:MyCompara.java

 package cn.tedu.collection_two;
 
 import java.util.Comparator;
 
 /**
  * 自定义比较器类,实现的是Comparator接口
  * @author cjn
  *
  */
 public class MyCompara implements Comparator<Point>{
 
    /**
      * 该方法返回值为整数类型
      * 只需要关注当前返回值的范围即可,
      * 如果方法的返回值是一个正数:升序排列
      * 如果方法的返回值是一个负数:降序排列
      * 如果方法的返回值等于0:相等
      */
    @Override
    public int compare(Point o1, Point o2) {
  //比较规则同上
        int len = (int)Math.sqrt(o1.getX()*o1.getX() + o1.getY()*o1.getY());
        int len2 = (int)Math.sqrt(o2.getX()*o2.getX() + o2.getY()*o2.getY());
        return len-len2;
    }
 
 }
 

(1)测试使用比较器对象类:Collection_sort05.java

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 /**
  * 测试使用比较器对象进行比较测试
  * @author cjn
  *
  */
 public class Collection_sort05 {
 
     public static void main(String[] args) {
         List<Point> list = new ArrayList<Point>();
         list.add(new Point(-2, 5));
         list.add(new Point(1, 1));
         list.add(new Point(10, -6));
         list.add(new Point(-2, -2));
         list.add(new Point(0, 3));
         System.out.println(list);
         
         //创建比较器对象
         MyCompara compara = new MyCompara();
         
         //比较集合中的元素大小
         Collections.sort(list,compara);
         System.out.println("比较后的集合:" + list);
    }
 
 }

(2)使用匿名内部类的方式实现:Collection_sort05.java

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
 /**
  * 测试使用比较器对象进行比较测试
  * @author cjn
  *
  */
 public class Collection_sort05 {
 
     public static void main(String[] args) {
         List<Point> list = new ArrayList<Point>();
         list.add(new Point(-2, 5));
         list.add(new Point(1, 1));
         list.add(new Point(10, -6));
         list.add(new Point(-2, -2));
         list.add(new Point(0, 3));
         System.out.println(list);
 
         //比较集合中的元素大小
         Collections.sort(list,new Comparator<Point>() {
             @Override
             public int compare(Point o1, Point o2) {
              //比较规则同上
                 int len = (int)Math.sqrt(o1.getX()*o1.getX() + o1.getY()*o1.getY());
                 int len2 = (int)Math.sqrt(o2.getX()*o2.getX() + o2.getY()*o2.getY());
                 return len-len2;
            }
             
        });
         System.out.println("比较后的集合:" + list);
    }
 
 }

测试结果:

 [Point [x=-2, y=5], Point [x=1, y=1], Point [x=10, y=-6], Point [x=-2, y=-2], Point [x=0, y=3]]
 比较后的集合:[Point [x=1, y=1], Point [x=-2, y=-2], Point [x=0, y=3], Point [x=-2, y=5], Point [x=10, y=-6]]

(3)利用自定义规则对字符串进行比较:按字符串长度比较

 package cn.tedu.collection_two;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
 /**
  * 自定义排序规则:按字符串长度对字符串进行排序
  * length()-o2.length()>0 升序
  * length()-o2.length()>0 降序
  * length()-o2.length()>0 同一级别
  * @author cjn
  *
  */
 public class Collection_sort06 {
 
  public static void main(String[] args) {
  List<String> list = new ArrayList<String>();
  list.add("超超");
  list.add("小超超小");
  list.add("小超超");
  list.add("小超超超小");
  list.add("小超超超超小");
  System.out.println("排序前:"+list);
  Collections.sort(list,new Comparator<String>() {
  @Override
  public int compare(String o1, String o2) {
  return o1.length()-o2.length();
  }
  });
  System.out.println("排序后:"+list);
  }
 
 }

输出结果

 排序前:[超超, 小超超小, 小超超, 小超超超小, 小超超超超小]
 排序后:[超超, 小超超, 小超超小, 小超超超小, 小超超超超小]
 补充:按照Unicode编码排序结果:[小超超, 小超超小, 小超超超小, 小超超超超小, 超超]

(4)利用自定义规则对字符串进行比较:按字母拼音顺序进行排序

 package cn.tedu.collection_two;
 
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Locale;
 
 public class Collection_sort6 {
 
  public static void main(String[] args) {
  List<String> list = new ArrayList<String>();
  list.add("中国");
  list.add("美国");
  list.add("英国");
  list.add("法国");
  list.add("德国");
  System.out.println("排序前:" + list);
  Collections.sort(list, new Comparator<String>() {
  @Override
  public int compare(String s1, String s2) {
  String o1 = "";
  String o2 = "";
  if (s1 != null) {
  o1 = s1;
  }
  if (s2 != null) {
  o2 = s2;
  }
  Collator instance = Collator.getInstance(Locale.CHINA);
  return instance.compare(o1, o2);
  }
  });
  System.out.println("排序后:" + list);
  Collections.reverse(list);
  System.out.println("排序后逆序:" + list);
  }
 
 }

输出结果

 排序前:[中国, 美国, 英国, 法国, 德国]   补充:按照Unicode编码排序结果:[中国, 德国, 法国, 美国, 英国]
 排序后:[德国, 法国, 美国, 英国, 中国]   分析:拼音顺序是:D F M Y Z
 排序后逆序:[中国, 英国, 美国, 法国, 德国]

 总结:

  1.使用Comparable接口定义比较规则时,参数类要实现Comparable接口,要将比较规则定义在参数类中,代码耦合性强,不建议使用;

  2.使用Comparator接口定义比较规则时,只需要新建一个内部类(实现Comparator接口)或匿名内部类,在里面进行定义比较规则,代码耦合度降低,推荐使用。

 

posted @ 2021-07-06 23:24  Coder_Cui  阅读(999)  评论(0编辑  收藏  举报