zoukankan      html  css  js  c++  java
  • Java提高十五:容器元素比较Comparable&Comparator深入分析

    我们经常用容器来存放元素,通常而言我们是不关系容器中的元素是否有序,但有些场景可能要求容器中的元素是有序的,这个时候用ArrayList  LinkedList  Hashtable HashMap HashSet 这些容器本身存放的时候就没有办法做到了,这个时候我们有两种思路:第一种思路:对刚刚我们提到的容器类的元素从新排序后存放,就是后面我们要介绍的利用Collections.sort 方法进行排序,第二种思路:是容器在添加元素的时候就进行大小的比较从而来保证元素的排序。下面我开始来详细介绍本节内容。

    一、排序概念

    在讲解上面的知识点前,我们首先需要知道最基础的知识,即什么是排序?

    排序:将一组数据按照某种规则进行排列顺序

    1、规则:

    • 基本数据类型:如数据,就是日常的大小顺序
    • 引用数据类型:
    1. 内置类(String,Integer等):内部已经指定好规则,直接使用即可。
    2. 自定义的类:需要按业务规则排序。 

    2、顺序:

    • 升序:从小到大
    • 降序:从大到小

    3、排列:算法,如:冒泡、选择、插入、shell、堆排序等等               

    二、冒泡排序

    上面说到排序的时候算法有很多种,那么这里我们介绍最简单的一种,即:冒泡排序。

    我们将会三个版本来进行演练:

    •  简易版:简单
    •  优化版:减少每趟次数
    •  最终版:考虑有序,减少趟数

    简易版:

    import java.util.Arrays;
    
    
    public class BubbleSort1 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            int[] arr ={9,8,7,6,5};        
            sort(arr);
            
        }
        //第一版本,很简单
        public static void sort(int[] arr){
            int len =arr.length;
            for(int j=0;j<len-1;j++){
                System.out.println("第"+(j+1)+"趟");
                for(int i=0;i<len-1;i++){
                    System.out.print("第"+(i+1)+"次");
                    if(arr[i]>arr[i+1]){
                        int temp = arr[i];
                        arr[i] =arr[i+1];
                        arr[i+1] =temp;
                    }
                    System.out.println(Arrays.toString(arr));
                }
            }
        }
        public static void sortSecond(int[] arr){
            System.out.println("第一趟");
            for(int i=0;i<arr.length-1;i++){
                System.out.print("第"+(i+1)+"次");
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1] =temp;
                }
                System.out.println(Arrays.toString(arr));
            }
            System.out.println("第二趟");
            for(int i=0;i<arr.length-1;i++){
                System.out.print("第"+(i+1)+"次");
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1] =temp;
                }
                System.out.println(Arrays.toString(arr));
            }
            System.out.println("第三趟");
            for(int i=0;i<arr.length-1;i++){
                System.out.print("第"+(i+1)+"次");
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1] =temp;
                }
                System.out.println(Arrays.toString(arr));
            }
            System.out.println("第四趟");
            for(int i=0;i<arr.length-1;i++){
                System.out.print("第"+(i+1)+"次");
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1] =temp;
                }
                System.out.println(Arrays.toString(arr));
            }
        
        }
        
        
        public static void sortFirst(int[] arr){
            System.out.println("第一趟");
            for(int i=0;i<arr.length-1;i++){
                System.out.print("第"+(i+1)+"次");
                if(arr[i]>arr[i+1]){
                    int temp = arr[i];
                    arr[i] =arr[i+1];
                    arr[i+1] =temp;
                }
                System.out.println(Arrays.toString(arr));
            }
            
            /*
            //第一趟 第一次
            System.out.println("第一趟 第一次");
            int i=0;
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] =arr[i+1];
                arr[i+1] =temp;
            }
            System.out.println(Arrays.toString(arr));
            System.out.println("第一趟 第二次");
            i++;
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] =arr[i+1];
                arr[i+1] =temp;
            }
            System.out.println(Arrays.toString(arr));
            
            System.out.println("第一趟 第三次");
            i++;
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] =arr[i+1];
                arr[i+1] =temp;
            }
            System.out.println(Arrays.toString(arr));
            
            System.out.println("第一趟 第四次");
            i++;
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i] =arr[i+1];
                arr[i+1] =temp;
            }
            System.out.println(Arrays.toString(arr));
            
            */
        }
    
    }

    说明:即每个元素需要和后面的元素比较arr.length -1 次;那么arr.length 个元素,需要进行arr.length -1 趟比较,于是就有了上面的代码。

    优化版本:

    package com.bjsxt.sort.bubble;
    
    import java.util.Arrays;
    
    public class BubbleSort2 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            int[] arr ={9,8,7,6,5};        
            sort(arr);
        }
        //第二版本,减少每一趟的次数
        public static void sort(int[] arr){
                int len =arr.length;
                for(int j=0;j<len-1;j++){ //趟数
                    System.out.println("第"+(j+1)+"趟");
                    for(int i=0;i<len-1-j;i++){ //次数
                        System.out.print("第"+(i+1)+"次");
                        if(arr[i]>arr[i+1]){
                            int temp = arr[i];
                            arr[i] =arr[i+1];
                            arr[i+1] =temp;
                        }
                        System.out.println(Arrays.toString(arr));
                    }
                }
            }
    
    }

    说明:即在每一趟元素比较的时候,其和每个元素比较的次数应该是不需要去重复进行前面比较过的,因此需要减少每趟比较的次数,即:地刺循环的时候变成了arr.length-1-j.

    最终版本:

    package com.bjsxt.sort.bubble;
    
    import java.util.Arrays;
    
    /**
     * 最终版本:考虑存在顺序
     * @author Administrator
     *
     */
    public class BubbleSort {
    
        /**
         * @param args
         */
        public static void main(String[] args) {        
            int[] arr ={1,2,9,3,4};
            sort1(arr);
    
            System.out.println("==========final============");
            arr =new int[]{9,1,2,3,4};
            sortFinal(arr);
        }
        //第二版本,减少每一趟的次数
        public static void sortFinal(int[] arr){
                boolean sorted= true;
                int len =arr.length;
                for(int j=0;j<len-1;j++){ //趟数
                    sorted =true; //假定有序
                    for(int i=0;i<len-1-j;i++){ //次数
                        if(arr[i]>arr[i+1]){
                            int temp = arr[i];
                            arr[i] =arr[i+1];
                            arr[i+1] =temp;
                            sorted =false; //假定失败
                        }
                        System.out.println(Arrays.toString(arr));
                    }
                    if(sorted){ //减少趟数
                        break;
                    }
                }
            }
    
        //第二版本,减少每一趟的次数
        public static void sort1(int[] arr){
                int len =arr.length;
                for(int j=0;j<len-1;j++){ //趟数
                    System.out.println("第"+(j+1)+"趟");
                    for(int i=0;i<len-1-j;i++){ //次数
                        System.out.print("第"+(i+1)+"次");
                        if(arr[i]>arr[i+1]){
                            int temp = arr[i];
                            arr[i] =arr[i+1];
                            arr[i+1] =temp;
                        }
                        System.out.println(Arrays.toString(arr));
                    }
                }
            }
    
    }

    说明:即如果有序了,则不需要进行比较了。

    三、TreeSet 和 TreeMap 

    在讲解TreeSet 和 TreeMap 前,我们要先介绍Comparable接口:

    • “排序”的实体类都实现了java.lang.Comparable 接口,Comparable 接口中只有一个方法,即:public int compareTo(T o);   0 相等  正数 负数
    • 实现了Comparable接口的类通过实现了的compareTo 方法从而确定该类对象的排序方式。

    1、内置类:

    Integer:

    public final class Integer extends Number implements Comparable<Integer> {
        //......
    
         public int compareTo(Integer anotherInteger) {
        int thisVal = this.value;
        int anotherVal = anotherInteger.value;
        return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
        }
    
    }

    Character:

    public final
    class Character extends Object implements java.io.Serializable, Comparable<Character> {
    
    public int compareTo(Character anotherCharacter) {
            return this.value - anotherCharacter.value;
        }
    
    }

    String:

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence{
    
    public int compareTo(String anotherString) {
        int len1 = count;
        int len2 = anotherString.count;
        int n = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
    
        if (i == j) {
            int k = i;
            int lim = n + i;
            while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
            }
        } else {
            while (n-- != 0) {
            char c1 = v1[i++];
            char c2 = v2[j++];
            if (c1 != c2) {
                return c1 - c2;
            }
            }
        }
        return len1 - len2;
        }
    
    }

    Date;

    public class Date
        implements java.io.Serializable, Cloneable, Comparable<Date>
    {
       public int compareTo(Date anotherDate) {
        long thisTime = getMillisOf(this);
        long anotherTime = getMillisOf(anotherDate);
        return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
        }
    }

     总结:

    /**
     * 内置引用数据类型(常用)的比较
     * @author Administrator
     *
     */
    public class Demo01 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Integer  a ; //根据基本数据类型大小
            Character ch; //根据Unicode编码顺序
            String str="abc"; //如果其中一个是例外一个起始开始的子串,返回长度之差
            String str2 ="abcd123";  //否则返回第一个不相等的unicode码之差
            System.out.println(str.compareTo(str2));
            str ="abc";
            str2 ="aad";
            System.out.println(str.compareTo(str2));
            
            
            java.util.Date d ;  //根据日期的长整形数比较
        }
    
    }

    2、内置类集合数组排序

    String:

    import java.util.Arrays;
    
    public class Demo02 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            String[] arr ={"a","abcd","abc","def"};
            //从到小排序 降序
            boolean sorted= true;
            int len =arr.length;
            for(int j=0;j<len-1;j++){ //趟数
                sorted =true; //假定有序
                for(int i=0;i<len-1-j;i++){ //次数
                    if(((Comparable)arr[i]).compareTo(arr[i+1])<0){
                        String temp = arr[i];
                        arr[i] =arr[i+1];
                        arr[i+1] =temp;
                        sorted =false; //假定失败
                    }
                }
                if(sorted){ //减少趟数
                    break;
                }
            }
            
            System.out.println(Arrays.toString(arr));
        }
    
    }

    Date:

    import java.util.Arrays;
    import java.util.Date;
    
    public class Demo03 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Date[] arr =new Date[3];
            arr[0] =new Date();
            arr[1] =new Date(System.currentTimeMillis()-1000*60*60);
            arr[2] =new Date(System.currentTimeMillis()+1000*60*60);
            //降序
            
            //从大到小排序 降序
                boolean sorted= true;
                int len =arr.length;
                for(int j=0;j<len-1;j++){ //趟数
                    sorted =true; //假定有序
                    for(int i=0;i<len-1-j;i++){ //次数
                        if(((Comparable)arr[i]).compareTo(arr[i+1])<0){
                            Date temp = arr[i];
                            arr[i] =arr[i+1];
                            arr[i+1] =temp;
                            sorted =false; //假定失败
                        }
                    }
                    if(sorted){ //减少趟数
                        break;
                    }
                }
                
                System.out.println(Arrays.toString(arr));
        }
    
    }

    可以看到我们可以抽出工具类来,因为大部分代码是一样的,抽出工具类,则需要考虑可以放多种数据类型,因此会考虑到泛型和Object[] 来存放,工具类如下:

    import java.util.Comparator;
    import java.util.List;
    
    
    
    /**
     * 排序
     * @author Administrator
     *
     */
    public class Utils {
        /**
         * List的排序+比较器
         * @param list
         * @param com
         */
        public static  <T> void sort(List<T> list,Comparator<T> com){
            //第一步:转成数组
            Object[] arr =list.toArray();
            sort(arr,com);
            //第二步:改变容器中对应的值
            for(int i=0;i<arr.length;i++){
                list.set(i, (T)(arr[i]));
            }
        }
        
        
        /**
         * 数组的排序 (降序)+Comparator接口
         * @param arr
         */
        public static <T> void sort(Object[] arr,Comparator<T> com){
            //从大到小排序 降序
                boolean sorted= true;
                int len =arr.length;
                for(int j=0;j<len-1;j++){ //趟数
                    sorted =true; //假定有序
                    for(int i=0;i<len-1-j;i++){ //次数
                        if(com.compare((T)arr[i], (T)arr[i+1])<0){
                            Object temp = arr[i];
                            arr[i] =arr[i+1];
                            arr[i+1] =temp;
                            sorted =false; //假定失败
                        }
                    }
                    if(sorted){ //减少趟数
                        break;
                    }
                }
        }
        
        
        
        /**
         * 容器排序 (使用泛型方法)
         */
        public static <T extends Comparable<T>> void sort(List<T> list){
            //第一步:转成数组
            Object[] arr =list.toArray();
            sort(arr);
            //第二步:改变容器中对应的值
            for(int i=0;i<arr.length;i++){
                list.set(i, (T)(arr[i]));
            }
            
        }
        
        
        /**
         * 数组排序 (使用泛型方法)
         */
        public static <T extends Comparable<T>> void sort(T[] arr){
            //从大到小排序 降序
            boolean sorted= true;
            int len =arr.length;
            for(int j=0;j<len-1;j++){ //趟数
                sorted =true; //假定有序
                for(int i=0;i<len-1-j;i++){ //次数
                    if(((Comparable)arr[i]).compareTo(arr[i+1])<0){
                        T temp = arr[i];
                        arr[i] =arr[i+1];
                        arr[i+1] =temp;
                        sorted =false; //假定失败
                    }
                }
                if(sorted){ //减少趟数
                    break;
                }
            }
        }    
        
        /**
         * 数组的排序 (降序)
         * @param arr
         */
        public static void sort(Object[] arr){
            //从大到小排序 降序
            boolean sorted= true;
            int len =arr.length;
            for(int j=0;j<len-1;j++){ //趟数
                sorted =true; //假定有序
                for(int i=0;i<len-1-j;i++){ //次数
                    if(((Comparable)arr[i]).compareTo(arr[i+1])<0){
                        Object temp = arr[i];
                        arr[i] =arr[i+1];
                        arr[i+1] =temp;
                        sorted =false; //假定失败
                    }
                }
                if(sorted){ //减少趟数
                    break;
                }
            }
            
        }
        
        
    }

    然后接下来,我们使用我们的工具类进行排序操作:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    
    public class Demo04 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Date[] arr =new Date[3];
            arr[0] =new Date();
            arr[1] =new Date(System.currentTimeMillis()-1000*60*60);
            arr[2] =new Date(System.currentTimeMillis()+1000*60*60);
            Utils.sort(arr); //降序
            System.out.println(Arrays.toString(arr));
            
            
            //字符串
            String[] arr2 ={"a","abcd","abc","def"};
            Utils.sort(arr2);
            System.out.println(Arrays.toString(arr2));
            
            
            System.out.println("==========List排序===========");
            //存放容器中
            List<String> list =new ArrayList<String>();
            list.add("a");
            list.add("abcd");
            list.add("abc");
            list.add("def");
            Utils.sort(list);
            System.out.println(list);
            
            
            
            
            System.out.println("==========使用Comparator 排序数组===============");
            arr2 =new String[]{"a","abcd","abc","def"};
            Utils.sort(arr2,new StringComp());
            System.out.println(Arrays.toString(arr2));
            
            System.out.println("==========List排序+比较器===========");
            list =new ArrayList<String>();
            list.add("a");
            list.add("abcd");
            list.add("abc");
            list.add("def");
            Utils.sort(list,new StringComp());
            System.out.println(list);
            
        }
    
    }
    /**
     * 排序规则的业务类
     * @author Administrator
     *
     */
    public class StringComp  implements java.util.Comparator<String>{
        
        /**
         * 按长度比较大小 
         * 正数 >
         * 负数 <
         * 0 ==
         */
        @Override
        public int compare(String o1, String o2) {
            int len1 =o1.length();
            int len2 =o2.length();        
            return -(len1-len2);
        }
        
    
    }

    上面我们使用的是自己定义的工具类,下面我们使用JDK 提供的工具类进行排序操作:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    /**
     * 使用Collections对容器的比较
     * 1、 public static <T> void sort(List<T> list, Comparator<? super T> c)  
     * 2、public static <T extends Comparable<? super T>> void sort(List<T> list)  
     * void sort(List<T> list)
     * @author Administrator
     *
     */
    public class Demo05 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            List<String> list =new ArrayList<String>();
            list.add("a");
            list.add("abcd");
            list.add("abc");
            list.add("def");
            Collections.sort(list,new StringComp());
            System.out.println(list);
            
            
            list =new ArrayList<String>();
            list.add("a");
            list.add("abcd");
            list.add("abc");
            list.add("def");
            Collections.sort(list);
            System.out.println(list);
            
            
        }
    
    }

    3、自定义类数据类型的排序

    对于自定义的数据类型排序,两种方法:1.实体类 实现java.lang.Comparable + compareTo    2.业务排序类  实现java.util.Comparator + compare 方法

    第二种方法,可以达到解耦的目的,比如实体类是一个calss 文件或者是其它部件提供的实体类等,可以通过定义业务排序类达到排序,更加灵活。

    实例一:Comparable 实现排序

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * 新闻条目实体类
     * @author Administrator
     *
     */
    public class NewsItem implements java.lang.Comparable<NewsItem>{
        //标题
        private String title;
        //点击量
        private int hits;
        //时间
        private Date pubTime;
        public NewsItem() {
        }
        
        
        public NewsItem(String title, int hits, Date pubTime) {
            super();
            this.title = title;
            this.hits = hits;
            this.pubTime = pubTime;
        }
    
    
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public int getHits() {
            return hits;
        }
        public void setHits(int hits) {
            this.hits = hits;
        }
        public Date getPubTime() {
            return pubTime;
        }
        public void setPubTime(Date pubTime) {
            this.pubTime = pubTime;
        }
    
        //时间降序 +点击量升序+标题降序
        @Override
        public int compareTo(NewsItem o) {
            int result =0;
            //比较 时间
            result =-this.pubTime.compareTo(o.pubTime); //降序
            if(0==result){ //时间相同
                //点击量 
                result =this.hits-o.hits; //升序
                if(0==result){ //点击量相同
                     //标题
                    result=-this.title.compareTo(o.title);//降序
                }
            }        
            
            return result;
        }
        
        @Override
        public String toString() {
            StringBuilder sb =new StringBuilder();
            sb.append("标题:").append(this.title);
            sb.append(",时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.pubTime));
            sb.append(",点击量:").append(this.hits).append("
    ");
            return sb.toString();
        }
    
        
    }
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Date;
    import java.util.List;
    
    import com.bjsxt.sort.innerType.Utils;
    
    /**
     * 使用Collections
     * @author Administrator
     *
     */
    public class NewsItemApp {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            List<NewsItem> news=new ArrayList<NewsItem>();
            news.add(new NewsItem("美国后怕了,逃跑了悲剧了",50,new Date(System.currentTimeMillis()-1000*60*60)));
            news.add(new NewsItem("中国登上钓鱼岛了,全国欢呼了",100,new Date()));
            news.add(new NewsItem("小日本终于听话了,泪流满面笑了",60,new Date(System.currentTimeMillis()-1000*60*60)));
            System.out.println("排序前:"+news);        
            //排序
            //Collections.sort(news);    
            Utils.sort(news);
            System.out.println("排序后"+news);
            
            
            
        }
    
    }

    实例二:Comparator 实现排序

    /**
     * 实体类
     * @author Administrator
     *
     */
    public class Goods {
        //商品名称
        private String name;
        //价格
        private double price;
        //收藏量
        private int fav;
        public Goods() {
            // TODO Auto-generated constructor stub
        }
        
        
        
        public Goods(String name, double price, int fav) {
            super();
            this.name = name;
            this.price = price;
            this.fav = fav;
        }
    
    
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
        public int getFav() {
            return fav;
        }
        public void setFav(int fav) {
            this.fav = fav;
        }
        
        
        @Override
        public String toString() {
            return "商品名:"+name+",收藏量"+this.fav+",价格:"+this.price+"
    ";
        }
    }
    /**
     * 按收藏量排序的业务类 (升序)
     * @author Administrator
     *
     */
    public class GoodsFavComp implements java.util.Comparator<Goods> {
    
        @Override
        public int compare(Goods o1, Goods o2) {
            return o1.getFav()-o2.getFav();
        }
    
    }
    /**
     * 按价格排序的业务类 (降序)
     * @author Administrator
     *
     */
    public class GoodsPriceComp implements java.util.Comparator<Goods> {
    
        @Override
        public int compare(Goods o1, Goods o2) {
            return -(o1.getPrice()-o2.getPrice()>0?1:(o1.getPrice()==o2.getPrice()?0:-1));
        }
    
    }
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class GoodsApp {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            List<Goods> list =new ArrayList<Goods>();
            list.add(new Goods("老马视频",100,2000));
            list.add(new Goods("老高视频",50,2000));
            list.add(new Goods("老裴视频",1000,1000));
            System.out.println("排序前:"+list);
        //    Collections.sort(list,new GoodsPriceComp());
            Collections.sort(list,new GoodsFavComp());
            System.out.println("排序后:"+list);
        }
    
    }

    4、TreeSet  TreeMap

    • TreeMap:确保key可以排序或者提供灵活的比较器
    • TreeSet:确保元素实体可以排序或者提供灵活比较器

    Treeset 数据中的元素是排序的并且不能够重复,也是实现了Set接口,但和实现了Set接口的HashSet的是不同的,HashSet 是无序,也不可重复。都是不可以重复,但是它们判断的条件是不一样的,HashSet 的前面我们说到过,其元素中的类型时一定要实现hashCode 和equals 的方法来达到去重的目的,但是TreeSet 不一定要实现这两个方法,是通过比较器来实现的去重,即要么Comparable  or  Comparator 当元素比较返回值为0 即相等重复。

    样例;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class Person {
        private final String name;//名称
        private final int handsome;//帅气指数
        
        public Person() {
            name =null;
            handsome =0;
        }
    
        public Person(String name, int handsome) {
            super();
            this.name = name;
            this.handsome = handsome;
        }
    
        public String getName() {
            return name;
        }
    
        
    
        public int getHandsome() {
            return handsome;
        }
    
        
        
        @Override
        public String toString() {
            return "姓名:"+this.name+",帅气指数:"+this.handsome+"
    ";
        }
        
        
    
    }
    import java.util.TreeSet;
    /**
     * 提供了 解耦的方式:业务排序类
     * @author Administrator
     *
     */
    public class TreeSetDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Person p1 =new Person("您",100);
            Person p2 =new Person("刘德华",1000);
            Person p3 =new Person("梁朝伟",1200);
            Person p4 =new Person("老裴",50);
            
            //依次存放到TreeSet容器中,使用排序的业务类(匿名内部类)
            TreeSet<Person> persons =new TreeSet<Person>(
                        new java.util.Comparator<Person>(){
    
                            @Override
                            public int compare(Person o1, Person o2) {
                                return -(o1.getHandsome()-o2.getHandsome());
                            }
                            
                        }
                    );
            persons.add(p1);
            //TreeSet 在添加数据时排序
            persons.add(p2);
            persons.add(p3);
            persons.add(p4);
            
            System.out.println(persons);
            
            /*
            //改变数据
            p4.setHandsome(100);
            p4.setName("您");
            */ 
            //p4 与p1 内容重复 
            System.out.println(persons);
            
        }
    
    }

    注意点:在添加数据的时候进行排序,数据更改不会影响到原来的顺序,不要改变数据,否则可能重复。

    样例2;采用实体类实现了Comparable接口:

    public class Worker implements java.lang.Comparable<Worker> {
        //工种
        private String type;
        //工资
        private double salary;
        public Worker() {
            // TODO Auto-generated constructor stub
        }
        
        
        public Worker(String type, double salary) {
            super();
            this.type = type;
            this.salary = salary;
        }
    
    
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public double getSalary() {
            return salary;
        }
        public void setSalary(double salary) {
            this.salary = salary;
        }
    
        /**
         * 按工资升序
         */
        @Override
        public int compareTo(Worker o) {
            return this.salary>o.salary?1:( this.salary==o.salary?0:-1);
        }
        
        @Override
        public String toString() {
            return "工种:"+this.type+",工资:"+this.salary+"
    ";
        }
        
    }
    import java.util.TreeSet;
    /**
     * 实体类实现Comparable 接口的应用
     * @author Administrator
     *
     */
    public class TreeSetDemo2 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Worker w1 =new Worker("垃圾回收员",12000);
            Worker w2 =new Worker("农民工",8000);
            Worker w3 =new Worker("程序猿",5000);
            
            TreeSet<Worker> employees =new TreeSet<Worker>();
            employees.add(w1);
            employees.add(w2);
            employees.add(w3);
            System.out.println(employees);
            
        }
    
    }

    最后TreeMap的演示:

    import java.util.Set;
    import java.util.TreeMap;
    
    public class TreeMapDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Person p1 =new Person("您",100);
            Person p2 =new Person("刘德华",1000);
            Person p3 =new Person("梁朝伟",1200);
            Person p4 =new Person("老裴",50);
            
            TreeMap<Person,String> map =new TreeMap<Person,String>(new java.util.Comparator<Person>(){
    
                @Override
                public int compare(Person o1, Person o2) {
                    return -(o1.getHandsome()-o2.getHandsome());
                }
                
            } );
            map.put(p1, "bjsxt");
            map.put(p2, "bjsxt");
            map.put(p3, "bjsxt");
            map.put(p4, "bjsxt");
            
            //查看键
            Set<Person> persons =map.keySet();
            System.out.println(persons);
        }
    
    }
    import java.util.TreeMap;
    
    public class TreeMapDemo02 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Worker w1 =new Worker("垃圾回收员",12000);
            Worker w2 =new Worker("农民工",8000);
            Worker w3 =new Worker("程序猿",5000);
            
            TreeMap<Worker,String > employees =new TreeMap<Worker,String >();
            employees.put(w1,"bjsxt");
            employees.put(w2,"bjsxt");
            employees.put(w3,"bjsxt");
            System.out.println(employees.keySet());
        }
    
    }

    四、Collections 工具类

    首先,此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。

    如果为此类的方法所提供的 collection 或类对象为 null,则这些方法都将抛出 NullPointerException

    这个类提供了很多静态方法来辅助我们操作集合类,如:

    方法摘要
    static
    <T> boolean
    addAll(Collection<? super T> c, T... elements)
              将所有指定元素添加到指定 collection 中。
    static
    <T> Queue<T>
    asLifoQueue(Deque<T> deque)
              以后进先出 (Lifo) Queue 的形式返回某个 Deque 的视图。
    static
    <T> int
    binarySearch(List<? extends Comparable<? super T>> list, T key)
              使用二分搜索法搜索指定列表,以获得指定对象。
    static
    <T> int
    binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
              使用二分搜索法搜索指定列表,以获得指定对象。
    static
    <E> Collection<E>
    checkedCollection(Collection<E> c, Class<E> type)
              返回指定 collection 的一个动态类型安全视图。
    static
    <E> List<E>
    checkedList(List<E> list, Class<E> type)
              返回指定列表的一个动态类型安全视图。
    static
    <K,V> Map<K,V>
    checkedMap(Map<K,V> m, Class<K> keyType, Class<V> valueType)
              返回指定映射的一个动态类型安全视图。
    static
    <E> Set<E>
    checkedSet(Set<E> s, Class<E> type)
              返回指定 set 的一个动态类型安全视图。
    static
    <K,V> SortedMap<K,V>
    checkedSortedMap(SortedMap<K,V> m, Class<K> keyType, Class<V> valueType)
              返回指定有序映射的一个动态类型安全视图。
    static
    <E> SortedSet<E>
    checkedSortedSet(SortedSet<E> s, Class<E> type)
              返回指定有序 set 的一个动态类型安全视图。
    static
    <T> void
    copy(List<? super T> dest, List<? extends T> src)
              将所有元素从一个列表复制到另一个列表。
    static boolean disjoint(Collection<?> c1, Collection<?> c2)
              如果两个指定 collection 中没有相同的元素,则返回 true
    static
    <T> List<T>
    emptyList()
              返回空的列表(不可变的)。
    static
    <K,V> Map<K,V>
    emptyMap()
              返回空的映射(不可变的)。
    static
    <T> Set<T>
    emptySet()
              返回空的 set(不可变的)。
    static
    <T> Enumeration<T>
    enumeration(Collection<T> c)
              返回一个指定 collection 上的枚举。
    static
    <T> void
    fill(List<? super T> list, T obj)
              使用指定元素替换指定列表中的所有元素。
    static int frequency(Collection<?> c, Object o)
              返回指定 collection 中等于指定对象的元素数。
    static int indexOfSubList(List<?> source, List<?> target)
              返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
    static int lastIndexOfSubList(List<?> source, List<?> target)
              返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
    static
    <T> ArrayList<T>
    list(Enumeration<T> e)
              返回一个数组列表,它按返回顺序包含指定枚举返回的元素。
    static
    <T extends Object & Comparable<? super T>>
    T
    max(Collection<? extends T> coll)
              根据元素的自然顺序,返回给定 collection 的最大元素。
    static
    <T> T
    max(Collection<? extends T> coll, Comparator<? super T> comp)
              根据指定比较器产生的顺序,返回给定 collection 的最大元素。
    static
    <T extends Object & Comparable<? super T>>
    T
    min(Collection<? extends T> coll)
              根据元素的自然顺序 返回给定 collection 的最小元素。
    static
    <T> T
    min(Collection<? extends T> coll, Comparator<? super T> comp)
              根据指定比较器产生的顺序,返回给定 collection 的最小元素。
    static
    <T> List<T>
    nCopies(int n, T o)
              返回由指定对象的 n 个副本组成的不可变列表。
    static
    <E> Set<E>
    newSetFromMap(Map<E,Boolean> map)
              返回指定映射支持的 set。
    static
    <T> boolean
    replaceAll(List<T> list, T oldVal, T newVal)
              使用另一个值替换列表中出现的所有某一指定值。
    static void reverse(List<?> list)
              反转指定列表中元素的顺序。
    static
    <T> Comparator<T>
    reverseOrder()
              返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序
    static
    <T> Comparator<T>
    reverseOrder(Comparator<T> cmp)
              返回一个比较器,它强行逆转指定比较器的顺序。
    static void rotate(List<?> list, int distance)
              根据指定的距离轮换指定列表中的元素。
    static void shuffle(List<?> list)
              使用默认随机源对指定列表进行置换。
    static void shuffle(List<?> list, Random rnd)
              使用指定的随机源对指定列表进行置换。
    static
    <T> Set<T>
    singleton(T o)
              返回一个只包含指定对象的不可变 set。
    static
    <T> List<T>
    singletonList(T o)
              返回一个只包含指定对象的不可变列表。
    static
    <K,V> Map<K,V>
    singletonMap(K key, V value)
              返回一个不可变的映射,它只将指定键映射到指定值。
    static
    <T extends Comparable<? super T>>
    void
    sort(List<T> list)
              根据元素的自然顺序 对指定列表按升序进行排序。
    static
    <T> void
    sort(List<T> list, Comparator<? super T> c)
              根据指定比较器产生的顺序对指定列表进行排序。
    static void swap(List<?> list, int i, int j)
              在指定列表的指定位置处交换元素。
    static
    <T> Collection<T>
    synchronizedCollection(Collection<T> c)
              返回指定 collection 支持的同步(线程安全的)collection。
    static
    <T> List<T>
    synchronizedList(List<T> list)
              返回指定列表支持的同步(线程安全的)列表。
    static
    <K,V> Map<K,V>
    synchronizedMap(Map<K,V> m)
              返回由指定映射支持的同步(线程安全的)映射。
    static
    <T> Set<T>
    synchronizedSet(Set<T> s)
              返回指定 set 支持的同步(线程安全的)set。
    static
    <K,V> SortedMap<K,V>
    synchronizedSortedMap(SortedMap<K,V> m)
              返回指定有序映射支持的同步(线程安全的)有序映射。
    static
    <T> SortedSet<T>
    synchronizedSortedSet(SortedSet<T> s)
              返回指定有序 set 支持的同步(线程安全的)有序 set。
    static
    <T> Collection<T>
    unmodifiableCollection(Collection<? extends T> c)
              返回指定 collection 的不可修改视图。
    static
    <T> List<T>
    unmodifiableList(List<? extends T> list)
              返回指定列表的不可修改视图。
    static
    <K,V> Map<K,V>
    unmodifiableMap(Map<? extends K,? extends V> m)
              返回指定映射的不可修改视图。
    static
    <T> Set<T>
    unmodifiableSet(Set<? extends T> s)
              返回指定 set 的不可修改视图。
    static
    <K,V> SortedMap<K,V>
    unmodifiableSortedMap(SortedMap<K,? extends V> m)
              返回指定有序映射的不可修改视图。
    static
    <T> SortedSet<T>
    unmodifiableSortedSet(SortedSet<T> s)
              返回指定有序 set 的不可修改视图。

     其中最主要的一个方法,也是本节关注点,就是sort 排序,在对Java无序类集合,如List(ArrayList/LinkedList)、HashSet(TreeSet有序)、HashMap等排序时,Java中一个公共的类Collections,提供了对Java集合排序等很好的方法sort。 但是有一个要求是sort方法的参数为<List list>  或<List list, Comparator<? super T>  c>,即排序对象要求必须是List类型。

    sort 方法的参数必须为List 的原因是,只有List可以定义排序的方法,让List中的元素改变在构建List时原始的相对位置(初始构建时,元素相对位置即为元素初始加入顺序)。HashSet、HashMap 在构建时,初始加入的元素已经按照元素的hashCode()方法的定义排好序。所以这里所说的HashSet 排序 和 HashMap 排序是指:将其中的元素导出到另一个集合中,对该载体集合排序。排序之后,原HashSet 和 HashMap 中元素顺序没有变。

    故而对Java无序类集合的排序问题,基本思路就是:将HashSet 或 HashMap 中的元素取出放入 List 中,对List 用 Collections.sort() 方法排序,之后输出排序后List中的元素,即为对Set/Map 中元素排序后的结果。注意HashSet、HashMap 中元素位置没有改变,依然只和 初始构建时,元素本身自定义的hashCode() 方法有关

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.Map;
    
    public class Test {
        public static void main(String[] args){
            ArrayList<String> listTest = new ArrayList<String>();
            listTest.add("bbc");
            listTest.add("abc");
            listTest.add("acb");        
            
            HashSet<String> setTest = new HashSet<String>();
            setTest.add("bbc");
            setTest.add("abc");
            setTest.add("acb");
            System.out.println("HashSet BeforeSort:");
            for(String s : setTest)
                System.out.println(s);
            
            HashMap<String, Integer> mapTest = new HashMap<String, Integer>();
            mapTest.put("bbc", 1);
            mapTest.put("abc", 2);
            mapTest.put("acb", 3);
            System.out.println("HashMap BeforeSort:");
            for(Map.Entry<String, Integer> entry : mapTest.entrySet())
                System.out.println(entry.getKey() + " " + entry.getValue());
            
            /*
             * List 
             */
            Collections.sort(listTest);
            Iterator<String> list_iter = listTest.iterator();
            while(list_iter.hasNext())
                System.out.println(list_iter.next());
            
            /*
             * Set
             */        
            LinkedList<String> setSort = new LinkedList<String>(setTest);        
            //Collections.sort(setSort);
            Comparator<String> setComp = Collections.reverseOrder();
            Collections.sort(setSort, setComp);
            /*LinkedList<String> setSort = new LinkedList<String>();
            for(String s : setTest)
                setSort.add(s);*/
            for(String s : setTest)
                System.out.println(s);
            for(String s : setSort)
                System.out.println(s);    
            
            /*
             * Map
             */        
            LinkedList<String> mapSort = new LinkedList<String>();
            mapSort.addAll(mapTest.keySet());
            //Collections.sort(mapSort);
            Comparator<String> mapComp = Collections.reverseOrder();
            Collections.sort(mapSort, mapComp);
            for(Map.Entry<String, Integer> entry : mapTest.entrySet())
                System.out.println(entry.getKey() + " " + entry.getValue());
            for(final Iterator<String> map_iter= mapSort.iterator(); map_iter.hasNext();)
                System.out.println(map_iter.next());        
    /*        
            LinkedList<Map.Entry<String, Integer>> mapEntry = new LinkedList<Map.Entry<String,Integer>>();
            mapEntry.addAll(mapTest.entrySet());
            Collections.sort(mapEntry, new Comparator<Map.Entry<String, Integer>>() {
                public int compare(Map.Entry<String, Integer> a, Map.Entry<String, Integer> b){
                    if(a.getValue() > b.getValue())
                        return -1;
                    else
                        return 1;                
                }
            });        
            
            for(Map.Entry<String, Integer> entry : mapEntry)
                System.out.println(entry.getKey() + " " +entry.getValue());
            for(Map.Entry<String, Integer> entry : mapTest.entrySet())
                System.out.println(entry.getKey() + " " + entry.getValue());*/        
        }
    }

    结果;

    HashSet BeforeSort:
    abc
    acb
    bbc
    HashMap BeforeSort:
    abc 2
    acb 3
    bbc 1
    //List AfterSort
    abc
    acb
    bbc
    //HashSet AfterSort
    abc
    acb
    bbc
    //setSort AfterSort (setSort is means HashSet to LinkedList)
    bbc
    acb
    abc
    //HashMap AfterSort
    abc 2
    acb 3
    bbc 1
    //mapSort AfterSort (mapSort is means HashMap to LinkedList)
    bbc
    acb
    abc

    小节:

    一、按key值排序
    假设HashMap存储的键-值对为(String,Integer),按key排序可以调用JDK函数sort(默认的按字典升序):
    Set<String> keySet = map.keySet();
     Collections.sort(keySet);
     for(Iterator<String> ite = keySet.iterator(); ite.hasNext();) {
         String temp = ite.next();
         System.out.println("key-value: "+temp+","+map.getValue(temp);
     }
    如果想要按字典的降序排列,则需改写sort方法里面的比较器Comparator:
    Collections.sort(keySet, new Comparator() {
         public int compare(Object o1, Object o2) {
            if(Integer.parseInt(o1.toString())>Integer.parseInt(o2.toString())
                 return 1;
            if(Integer.parseInt(o1.toString())==Integer.parseInt(o2.toString())
                return 0;
             else
                 return -1;
         }
     });
    
    
    
    
    二、按value值排序
    1)方法一:用两个list链表实现
    List<String> keyList = new LinkedList<String>();
     keyList.addAll(map.keySet());
     List<Integer> valueList = new LinkedList<Integer>();
     valueList.addAll(map.values());
     for(int i=0; i<valueList.size(); i++)
        for(int j=i+1; j<valueList.size(); j++) {
           if(valueList.get(j)>valueList.get(i)) {
               valueList.set(j, valueList.get(i));
               valueList.set(i, valueList.get(j));
               //同样调整对应的key值
              keyList.set(j, keyList.get(i));
               keyList.set(i, kyeList.get(j));
           }
    然后依次把key值和对应value值重新装入HashMap即可。
    2)方法二:改写JDK提供的Comparator接口方法compare
     List<Map.Entry<String, Integer>> list = new LinkedList<Map.Entry<String, Integer>>();
     list.addAll(map.entrySet());
     Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
        public int compare(Map.Entry obj1, Map.Entry obj2) {//从高往低排序
           
            if(Integer.parseInt(obj1.getValue().toString())<Integer.parseInt(obj2.getValue().toString()))
                return 1;
            if(Integer.parseInt(obj1.getValue().toString())==Integer.parseInt(obj2.getValue().toString()))
                return 0;
            else
               return -1;
        }
     });
     for(Iterator<Map.Entry<String, Integer>> ite = list.iterator(); ite.hasNext();) {
          Map.Entry<String, Integer> map = ite.next();
         System.out.println("key-value: " + map.getKey() + "," + map.getValue());
     }
  • 相关阅读:
    创建自动执行存储过程
    创建链接服务器
    SQLServer查询特殊符号处理
    SQL Server维护计划自动备份数据库
    SQL Server收缩数据库&列出所有表的数据条数
    SQL server日志文件过大处理方式
    SQL Server批量删除数据库表
    done apple经理面 匹配括号但是不能用stack
    done Beaconfire中国小哥中规中矩screening
    done marlabs挺难的screening
  • 原文地址:https://www.cnblogs.com/pony1223/p/7881885.html
Copyright © 2011-2022 走看看