zoukankan      html  css  js  c++  java
  • Java 从入门到进阶之路(二十五)

    在之前的文章我们介绍了一下 Java 中的  集合框架中的Collection 的子接口 List的 增删改查和与数组间相互转换的方法,本章我们来看一下 Java 集合框架中的Collection 的子接口 List 的另外一些方法。

    我们在使用集合的时候难免会对其中的元素进行排序,因为 Set 集合本身是无序的,所以本章将着重讲解 List 集合,如下:

     1 import java.util.ArrayList;
     2 import java.util.Collections;
     3 import java.util.List;
     4 import java.util.Random;
     5 
     6 /**
     7  * 排序集合元素
     8  * 排序集合使用的是集合的工具类 Collections 的静态方法 sort
     9  * 排序仅能对 List 集合进行,因为 Set 部分实现类是无序的
    10  * */
    11 public class Main {
    12     public static void main(String[] args) {
    13         List<Integer> list = new ArrayList<Integer>();
    14         Random random = new Random();
    15         for(int i=0;i<10;i++){
    16             list.add(random.nextInt(100));
    17         }
    18         System.out.println(list); // [49, 24, 29, 59, 56, 1, 1, 5, 49, 60]
    19 
    20         Collections.sort(list);
    21         System.out.println(list); // [1, 1, 5, 24, 29, 49, 49, 56, 59, 60]
    22     }
    23 }

    在上面的代码中,我们随机生成了一些正数并添加到 List 集合中,我们通过 sort 方法,系统变自动按照自然数的排列方法为我们做好了排序,很是方便,那如果 List 中使我们自己定义的内容,比如说一个类,那该如何排序呢,如下:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    /**
     * 排序集合元素
     * 排序集合使用的是集合的工具类 Collections 的静态方法 sort
     * 排序仅能对 List 集合进行,因为 Set 部分实现类是无序的
     */
    public class Main {
        public static void main(String[] args) {
            List<Point> list = new ArrayList<Point>();
            list.add(new Point(1, 2));
            list.add(new Point(2, 3));
            list.add(new Point(4, 2));
            list.add(new Point(2, 5));
            list.add(new Point(9, 3));
            list.add(new Point(7, 1));
            System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (9, 3), (7, 1)]
            // Collections.sort(list); // 编译错误,不知道 Point 排序规则
            /**
             * sort 方法要求集合必须实现 Comparable 接口
             * 该接口用于规定实现类事可以比较的
             * 其中一个 compareTo 方法时用来定义比较大小的规则
             * */
            Collections.sort(list);
            System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (7, 1), (9, 3)]
    
        }
    }
    
    class Point implements Comparable<Point> { // 定义为泛型 T 类型
        private int x;
        private int y;
    
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        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;
        }
    
        @Override
        public String toString() {
            return "(" + x + ", " + y + ")";
        }
    
        /**
         * 当实现了 Comparable 接口后,需要重写下面的方法
         * 该方法的作用是定义当前对象与给定参数对象比较大小的规则
         * 返回值为一个 int 值,该值表示大小关系
         * 它不关注具体的取值是多少,而关注的是取值范围
         * 当返回值 >0 时:当前对象不参数对象大
         * 当返回值 <0 时:当前对象比参数对象小
         * 当返回值 =0 时:两个对象相等
         */
        @Override
        public int compareTo(Point o) {
            /**
             * 比较规则,点到原点的距离长的打
             * */
            int len = this.x * this.x + this.y * this.y;
            int olen = o.x * o.x + o.y * o.y;
            return len - olen;
        }
    }

    在上面的代码中,我们跟之前一样定义了一个 Point 类,然后实例化后存入 list 集合中,如果我们相对 Point 进行排序,如果直接调用 sort 方法会报错,这是由于编译器不知道我们定义的 Point 类的排序规则,所以我们需要通过接口 Comparable 接口来自定义排序规则,如下图:

    我们可以通过坐标系中点到原点的距离来判断 Point 的大小,即 x*x+y*y 的大小,然后通过重写 compareTo 方法来实现 sort 。

    实际上虽然能实现,但是并不理想,为了实现一个 sort 方法,要求我们的集合元素必须实现 Comparable 接口并且定义比较规则,这种我们想使用某个功能,而它要求我们修改程序的现象称为“侵入性”。修改的代码越多,侵入性越强,越不利于程序的扩展。

    我们再来看一下下面的排序:

     1 import java.util.ArrayList;
     2 import java.util.Collections;
     3 import java.util.List;
     4 
     5 public class Main {
     6     public static void main(String[] args) {
     7         List<String> list1 = new ArrayList<String>();
     8         list1.add("Java");
     9         list1.add("c++");
    10         list1.add("Python");
    11         list1.add("PHP");
    12         Collections.sort(list1);
    13         System.out.println(list1); // [Java, PHP, Python, c++]
    14 
    15         List<String> list2 = new ArrayList<String>();
    16         list2.add("孙悟空");
    17         list2.add("猪八戒");
    18         list2.add("唐僧");
    19         list2.add("六小龄童");
    20         Collections.sort(list2);
    21         System.out.println(list2); // [六小龄童, 唐僧, 孙悟空, 猪八戒]
    22 
    23     }
    24 }

    在上面的排序中,当我们对字母或汉字进行排序时,其实是比的第一个字的 Unicode 码,那如果我们不使用 Comparable 的接口该如何自定义我们想要的实现规则呢?比如根据字符串的长度来进行排序,其实 sort 有一个额外的重载方法来实现我们想要的结果,如下:

     1 import java.util.ArrayList;
     2 import java.util.Collections;
     3 import java.util.Comparator;
     4 import java.util.List;
     5 
     6 public class Main {
     7     public static void main(String[] args) {
     8         /**
     9          * 重载的 sort 方法要求传入一个额外的比较器
    10          * 该方法不再要求集合元素必须实现 Comparable 接口
    11          * 并且不再使用集合元素资深的比较规则排序了
    12          * 而是根据给定的这个额外的比较器的比较规则对集合元素进行排序
    13          * 实际开发中也推荐使用这种方式进行集合元素排序
    14          * 若集合元素是自定义的
    15          * 创建比较器时推荐使用匿名内部类的形式
    16          */
    17         List<String> list1 = new ArrayList<String>();
    18         list1.add("Java");
    19         list1.add("c++");
    20         list1.add("Python");
    21         list1.add("PHP");
    22         MyComparator myComparator1 = new MyComparator();
    23         Collections.sort(list1, myComparator1); // 重载 sort
    24         System.out.println(list1); // [c++, PHP, Java, Python]
    25 
    26         List<String> list2 = new ArrayList<String>();
    27         list2.add("孙悟空");
    28         list2.add("猪八戒");
    29         list2.add("唐僧");
    30         list2.add("六小龄童");
    31         // 匿名内部类形式创建
    32         Comparator<String> myComparator2 = new Comparator<String>() {
    33             @Override
    34             public int compare(String o1, String o2) {
    35                 return o1.length() - o2.length();
    36             }
    37         };
    38         Collections.sort(list2, myComparator2); // 重载 sort
    39         System.out.println(list2); // [唐僧, 孙悟空, 猪八戒, 六小龄童]
    40 
    41     }
    42 }
    43 
    44 /**
    45  * 定义一个额外的比较器
    46  * 该方法用来定义 o1 和 o2 的比较
    47  * 若返回值 >0:o1>o2
    48  * 若返回值 <0:o1<o2
    49  * 若返回值 =0:两个对象相等
    50  */
    51 class MyComparator implements Comparator<String> {
    52     @Override
    53     public int compare(String o1, String o2) {
    54         /**
    55          * 字符串中字符多的大
    56          * */
    57         return o1.length() - o2.length();
    58     }
    59 }

        

  • 相关阅读:
    30 algorithm questions study
    Binary Tree: Write a function to return count of nodes in binary tree which has only one child.
    分布式排序
    android开发中,工程前面有感叹号的解决办法
    android导入工程出现红色感叹号
    INSTALL_FAILED_MISSING_SHARED_LIBRARY错误解决方法
    安卓手机铃声怎么设置
    如何开启Mysql远程访问
    android 链接mysql数据库
    android 连接mysql数据库问题
  • 原文地址:https://www.cnblogs.com/weijiutao/p/12070234.html
Copyright © 2011-2022 走看看