【学习笔记】java集合框架2

一. TreeSet 元素之间是有序的

 1 package com.sort;
 2 
 3 import java.util.Set;
 4 import java.util.TreeSet;
 5 
 6 public class TestTreeSet {
 7     
 8     /**
 9      * 
10      * @param args
11      */
12     public static void main(String[] args){
13         Set set = new TreeSet();
14         set.add(null);
15         set.add("1");
16         set.add("2");
17         set.add("3");
18         set.add(new Dog(1,"aa"));
19         set.add(new Dog(2,"bb"));
20         set.add(new Dog(3,"cc"));
21         System.out.println(set);
22         
23     }
24 }

此段代码报错, 原因是TreeSet是有序的, 会对他们的自然顺序进行排序, 由于第14行加进去的是null, 而15行加进去的是"1", null 和 "1"无法进行比较, 所以编译器报错.

同理, 在第15~17行, 和第18~20行中, 字符串和对象又不能进行比较, 所以编译器又报错.  

现在注释掉, 如下代码:

package com.sort;

import java.util.Set;
import java.util.TreeSet;

public class TestTreeSet {
    
    /**
     * 
     * @param args
     */
    public static void main(String[] args){
        Set set = new TreeSet();
        
        //set.add(null);
        set.add("1");
        set.add("2");
        set.add("3");
        //set.add(new Dog(1,"aa"));
        //set.add(new Dog(2,"bb"));
        //set.add(new Dog(3,"cc"));
        System.out.println(set);
        
    }
}

运行结果:

[1, 2, 3]

 

我们把加入顺序改一下

set.add("2");
set.add("3");
set.add("1");

结果还是:

[1, 2, 3]

由此可见, TreeSet会对加入的元素进行排序后输出, 比较的机理是对字符串的ASCALL码进行比较!

 

我们再来看下面的代码:

package com.sort;

import java.util.Set;
import java.util.TreeSet;

public class TestTreeSet {
    
    public static void main(String[] args){
        Set set = new TreeSet();
        
        //set.add(null);
        //set.add("2");
        //set.add("3");
        //set.add("1");
        set.add(new Dog(1,"aa"));
        set.add(new Dog(2,"bb"));
        set.add(new Dog(3,"cc"));
        System.out.println(set);
        
    }
}

这里面无法编译成功, 说明Dog这个对象无法进行排序, 那么, 有个问题, String也是一个类, 那么它的对象 "1""2""3"怎么可以进行排序比较呢?
查看String的源码:

【学习笔记】java集合框架2_第1张图片

可以看出有个 java.lang.Comparable 实现了这个接口.

我们查看文档: 对于Comparable这个接口实现类的一些说明, 有如下说明:

public interface Comparable<T>
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

方法是:

compareTo

int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

 

为了能对Dog这个对象进行比较, 要在Dog类中实现Compare接口的方法, Compare的方法是CompareTo

补充知识点:

java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
 用法:
result = object instanceof class
参数:
Result:布尔类型。
Object:必选项。任意对象表达式。
Class:必选项。任意已定义的对象类。
 说明:
 如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false

 

在Dog.java 类中, 代码如下:

package com.sort;

public class Dog implements Comparable {
    int dogid;
    String dogName;
    public Dog(int dogid, String dogName) {
        this.dogid = dogid;
        this.dogName = dogName;
    }
    
    public int compareTo(Object obj){
        if (obj == null){
            return -1; //对象是空的,那么就排在前面
        }else{
            //如果obj是Dog的一个实例(对象)
            if (obj instanceof Dog){
                //虽然obj是Dog的一个实例, 但是obj是定义为一个Object对象,所以强制转换成Dog类
                Dog tempDog = (Dog) obj;//强制转换
                if (this.dogid == tempDog.dogid){
                    return 0;
                }else if (this.dogid < tempDog.dogid){
                    return -1;
                }else {
                    return 1;
                }
            }
        }
        return 0;
    }

}

运行结果:

[com.sort.Dog@659e0bfd, com.sort.Dog@2a139a55, com.sort.Dog@15db9742]

 

看不出哪个是哪个,  那么, 重写一下toString方法:

package com.sort;

public class Dog implements Comparable {
    int dogid;
    String dogName;
    public Dog(int dogid, String dogName) {
        this.dogid = dogid;
        this.dogName = dogName;
    }
    

    @Override
    public String toString() {
        return super.toString() + "[id = "+ dogid + dogName + "]";
    }



    public int compareTo(Object obj){
        if (obj == null){
            return -1; //对象是空的,那么就排在前面
        }else{
            //如果obj是Dog的一个实例(对象)
            if (obj instanceof Dog){
                //虽然obj是Dog的一个实例, 但是obj是定义为一个Object对象,所以强制转换成Dog类
                Dog tempDog = (Dog) obj;//强制转换
                if (this.dogid == tempDog.dogid){
                    return 0;
                }else if (this.dogid < tempDog.dogid){
                    return -1;
                }else {
                    return 1;
                }
            }
        }
        return 0;
    }

}

运行结果:

[com.sort.Dog@659e0bfd[id = 1aa], com.sort.Dog@2a139a55[id = 2bb], com.sort.Dog@15db9742[id = 3cc]]

改变一下顺序, 打印出来的结果相同.

 

再来看一下 TreeSet 的一个性质, 看如下代码:

 1 package com.sort;
 2 
 3 import java.util.Iterator;
 4 import java.util.Set;
 5 import java.util.TreeSet;
 6 
 7 public class TestTreeSet {
 8     
 9     public static void main(String[] args){
10         
11         //TestTreeSet.onemathod();
12         TestTreeSet.twomathod();
13     }
14 
15     private static void twomathod() {
16         TreeSet treeset = new TreeSet();
17         treeset.add("4");
18         treeset.add("2");
19         treeset.add("1");
20         treeset.add("3");
21         treeset.add("1");
22         //System.out.println(treeset);
23         Iterator iterator = treeset.iterator();//迭代器
24         while(iterator.hasNext()){
25             System.out.print(iterator.next() + "  ");
26         }
27     }
28 
29     private static void onemathod() {
30         Set set = new TreeSet();
31         //set.add(null);
32         //set.add("2");
33         //set.add("3");
34         //set.add("1");
35         set.add(new Dog(1,"aa"));
36         set.add(new Dog(2,"bb"));
37         set.add(new Dog(3,"cc"));
38         System.out.println(set);
39     }
40 }
View Code

看到第16到21行, 其中有两个1, 但是结果是:

1  2  3  4  

因为TreeSet继承与Set, 所以它也有Set的这个性质.

二. TreeMap

TreeMap.put("键值", "值");

package com.sort;

import java.util.TreeMap;

public class TestTreeMap {
    public static void main(String[] args){
        TreeMap treemap = new TreeMap();
        treemap.put("1", "我");    
        treemap.put("3", "的学生");
        treemap.put("2", "是福建师范大学");
        System.out.println(treemap);
    }
}

运行结果: 

{1=我, 2=是福建师范大学, 3=的学生}

同样的, 只能进行相同类型的比较, 不能在键值中比较 整型 和 字符型.

总结:

TreeSet的特点: 只能加入相同的对象类型。

         加入的对象必须实现Comparable接口。

        不是线程安全的集合类

TreeMap的特点:键只能是相同的对象类型。

         加入的键对象必须实现Comparable接口。

         不是线程安全的集合类。

下面来说明一下, 使用TreeSet, 顺序都是从 小到大的ASCALL 码进行排序, 可否让它按照其他顺序进行排序呢?  有一种方法, 就是对Comparable 的实现方法进行重写, 但是这样不是有效的方法, 所以, 我们可以用Comparator来实现这个方法.

在文档中查看Comparator接口

public interface Comparator<T>
强行对某个对象 collection 进行整体排序 的比较函数。

再看看它的方法:

方法摘要
 int    compare(T o1, T o2) 
          比较用来排序的两个参数。
 boolean    equals(Object obj) 
          指示某个其他对象是否“等于”此 Comparator。
 

 

根据文档中的这些说明, 我们可以进行代码的编写来实现那个从大到小的编程:
新建一个类来实现Comparator接口的compare方法
StringComparator.java

package com.sort;

import java.util.Comparator;

//重新建立一个类, 来实现Comparator这个接口
public class StringCompartor implements Comparator {
    public int compare(Object obj1, Object obj2){
        String str1 = (String)obj1;
        String str2 = (String)obj2;
        
        //因为是逆序, 所以只要返回正序的compareTo的相反值就可以
        return -(str1.compareTo(str2));
    }
}

Main函数:

package com.sort;

import java.util.TreeSet;

public class TestTreeSet2 {
    public static void main(String[] args){
        
        /*
        TreeSet的构造方法摘要
        TreeSet() 
                  构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。
        TreeSet(Collection<? extends E> c) 
                  构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。
        TreeSet(Comparator<? super E> comparator) 
                  构造一个新的空 TreeSet,它根据指定比较器进行排序。
        TreeSet(SortedSet<E> s) 
                  构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。
        */
        
        StringCompartor stringcomparator = new StringCompartor();
        TreeSet treeset = new TreeSet(stringcomparator);//TreeSet构造方法的第三个
        
        treeset.add("2");
        treeset.add("1");
        treeset.add("3");
        System.out.println(treeset);
    }
}

运行结果:

[3, 2, 1]


总结:

Comparable:内部比较器
内部比较器,当对象加入有序的集合。
Comparator:外部比较器
外部比较器:当改变内部已经排好序的对象。或者原先的对象没有Comparable。

 

你可能感兴趣的:(Java集合框架)