Collection接口中的子接口List接口与Set接口

起始目录导引:

Collection接口

              |------List接口:存储有序的,可以重复的元素

                     |----------ArrayList(主要的实现类)LinkedListVector

              |------Set接口:

                     |----------HashSetLinkedHashSetTreeSet

  Map接口:存储"--"对的数据:

              |------HashMapLinkedHashMapTreeMapHashTable(子类:properties)

 

 

导包用:Ctrl+Shift+O;

接口创建对象的写法:接口名  变量名=new  接口内的类名();

 

 

总、Collection接口:

 

                                                   壹     

                                Collection接口的List子接口:有序的

一、Collection接口的实现:

 

  1. Collection是一个接口,我们通过Collection接口的子接口的一个具体实现类ArrayList来说明了Collection中含有的一些方法;创建接口对象的写法:接口名  变量名=new  子接口内的实现方法的类名();

关于Collection接口的代码介绍:(代码中存在多个单元测试@Test如果想运行其中的某个,需要选中@Test下方的方法名(只要方法名,小括号除外)-->右键-->Run As-->JUnit Test

Collection接口中的方法的代码解析:

package com.atguigu.collection;



import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collection;

import java.util.Date;

import java.util.Iterator;



import org.junit.Test;



/*

 * 1、存储对象可以考虑:①、数组;②、集合

 * 2、数组存储对象的特点:Student[] stu=new Student[20];stu[0]=new Student();........

 *      -->弊端:①、一旦创建,长度不可变。如:银行存顾客,如果用数组,受限制。②、真实的数组存放的对象的个数是不可知的。

* 3、集合

 *      Collection接口

 *              |------List接口:存储有序的,可以重复的元素

 *                     |----------ArrayList、LinkedList、Vector

 *              |------Set接口:

 *                     |----------HashSet、LinkedHashSet、TreeSet

 *      Map接口:存储"键--值"对的数据:

 *              |------HashMap、LinkedHashMap、TreeMap、HashTable(子类:properties)

 *

 * */

public class TestCollection {

    @Test

    public void testCollection3() {

        Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。

        //1、size()方法:返回集合中元素的个数

        System.out.println(coll.size());

        //2、add(Object obj):向集合中添加元素

        coll.add(123);

        coll.add("AA");

        coll.add(new Date());

        coll.add("BB");

//      coll.add(new Person("MM",23));

        Collection coll1=new ArrayList();

        coll1.add(123);

        coll1.add(new String("AA"));

        //10、removeAll(Collection coll):从当前几何中删除包含在coll中的元素。

        coll.removeAll(coll1);

        System.out.println(coll);

        //11、equals(Object obj):两个集合是否完全相同

        //12、hashCode():计算集合中的Hash值,

        System.out.println("########");

        //13、toArray():将集合转化成数组

        Object[] obj=coll.toArray();

        for(int i=0;i<obj.length;i++) {   //数组的遍历

            System.out.println(obj[i]);

        }

        //14、iterator():返回一个Iterator接口实现类的对象,进而实现集合的遍历;遍历集合中的元素

        Iterator iterator=coll.iterator();

        //集合的遍历方式一:用System.out.println(iterator.next());

//      System.out.println(iterator.next());

//      System.out.println(iterator.hasNext());

//      System.out.println(iterator.hashCode());

//      System.out.println(iterator.next());

        System.out.println("分隔线------------------");

//      //集合的遍历方式二:使用for语句

//      for(int i=0;i<coll.size();i++) {

//          System.out.println(iterator.next());

//      }

        //方式三:常用

        while(iterator.hasNext()) {//下一个是否有hash值

            System.out.println(iterator.next());

        }

    }

    @Test

    public void testCollection2() {

        Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。

        //1、size()方法:返回集合中元素的个数

        System.out.println(coll.size());

        //2、add(Object obj):向集合中添加元素

        coll.add(123);

        coll.add("AA");

        coll.add(new Date());

        coll.add("BB");

//      Person p=new Person("MM",23);

//      coll.add(p);       两句和为一句:coll.add(new Person(“MM”,23));

//      System.out.println(p); //true

       

//      boolean b2=coll.contains(new Person("MM",23));

//      System.out.println(b2);    //false

        //6、contains(Object obj):判断集合中是否包含指定的obj元素。如果包含,返回true;反之,返回false。

        //判断依据:根据元素所在类的equals()方法。

        //明确:如果存入集合中的元素是自定义类的对象。要求:自定义类要重写equals()方法!

        boolean b1=coll.contains(23);

        System.out.println(b1);

        //7、containsAll(Collection coll):判断当前集合中是否包含coll中所有的元素

        Collection coll1=new ArrayList();

        coll1.add(123);

        coll1.add(new String("AA"));

        boolean b3=coll.containsAll(coll1);   //true

        System.out.println("#"+b3);

        coll1.add(456);

        //8、returnAll(Collection coll1):形参为一个集合;求当前集合与coll的共有元素,返回给当前集合

        coll.retainAll(coll1);

        System.out.println(coll);

        //9、remove(Object obj):删除集合中的obj元素,删除成功返回true;反之false。

        boolean b4=coll.remove("BB");

        System.out.println(b4);

        //10、

       

    }

    @Test//单元测试

    public void testCollection1() {

        Collection coll=new ArrayList();//Collection是一个接口,接口创建时new的是一个接口内的类。

        //1、size()方法:返回集合中元素的个数

        System.out.println(coll.size());

        //2、add(Object obj):向集合中添加元素

        coll.add(123);

        coll.add("AA");

        coll.add(new Date());

        coll.add("BB");

        System.out.println(coll.size());  //4

        //3、addAll(Collection coll):将形参coll1中包含的所有元素添加到当前集合中

        Collection coll1=Arrays.asList(1,2,3); //数组转化为了集合。

        coll.addAll(coll1);

        System.out.println(coll.size());  //7

        //查看集合元素:直接打印引用名即可查看集合元素

        System.out.println(coll);

        //4、isEmpty():判断集合是否为空

        System.out.println(coll.isEmpty());   //false

        //5、clear():清空集合元素

        coll.clear();

        System.out.println(coll.isEmpty());   //true

    }

}

 

 

 

二、集合遍历的方法的代码解析(代码中介绍了很多遍历方法):

package com.atguigu.collection;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Date;

import java.util.Iterator;



import org.junit.Test;



public class TestIterator {

    //面试题:

    @Test

    public void testFor3() {

        String[] str=new String[] {"AA","BB","C","D","E"};

        for(String s:str) {

            s="MM";//此处的s是新定义的局部变量,其值的修改不会对str本身造成修改;并不改变真正集合中元素的值

            System.out.println(s);

        }

        for(int i=0;i<str.length;i++) {

            System.out.println(str[i]);

        }

    }
//结果:

//MM

//MM

//  MM

//  MM

//  MM

//  AA

//  BB

//  C

//  D

//  E

   

    @Test

    public void testFor2() {

        String[] str=new String[] {"AA","BB","C","D","E"};

        for(int i=0;i<str.length;i++) {

            str[i]=i+" ";      //将集合中的真正元素的值给改了

        }

        for(int i=0;i<str.length;i++) {

            System.out.println(str[i]);

        }

    }

   

    //使用增强for循环实现数组的遍历

    @Test

    public void testFor1() {

        String str[]=new String[] {"123","Bb","ABC","Hello"};

        for(String s:str) {

            System.out.println(s);

        }

    }

   

    //使用增强for循环实现集合的遍历

    @Test  

    public void testFor() {

        Collection coll=new ArrayList();

        coll.add(123);

        coll.add(new String("AA"));

        coll.add(new Date());

        coll.add("ABCDEF");

        coll.add(new Person("MM",23));

       

        for(Object i:coll) {   //要遍历元素的类型 变量:要遍历的集合;局部变量相当于每次取出coll集合中的一个赋给i;

            System.out.println(i);

        }

    }

   

    //使用迭代器遍历集合元素

    @Test  

    public void test1() {

        Collection coll=new ArrayList();

        coll.add(123);

        coll.add(new String("AA"));

        coll.add(new Date());

        coll.add(new Person("MM",23));

       

        Iterator i=coll.iterator();

        while(i.hasNext()) {//hasNext():判断集合中的下一个元素是否有值,从而可以知道是否存在下一个元素。

            System.out.println(i.next());//执行.next();:会把当前的集合中元素的值返回,并且指向下一个元素

        }

    }

   

//  @Test

/*          有错误的写法        */

//  public void test2() {

//      Collection coll=new ArrayList();

//      coll.add(123);

//      coll.add(new String("AA"));

//     

//      coll.add(new Date());

//      coll.add(new Person("MM",23));

//     

//      Iterator i=coll.iterator();

//      while(i.next()!=null) {//hasNext():判断集合中的下一个元素是否有值,从而可以知道是否存在下一个元素。

//          System.out.println(i.next());//执行.next();:会把当前的集合中元素的值返回,并且指向下一个元素

//      }   java.util.NoSuchElementException错误

//  }

}

 

 

 

三、ArrayList及List的常用方法:

 

常用方法代码实现解析:

package com.atguigu.collection;

import java.awt.List;

import java.util.ArrayList;



import org.junit.Test;

/*

 * List常用的方法:

 *      增(add(Object obj))、删(remove)、改(set(int index,Object obj));

 *      查(get(int index))、插(add(int index,Object ele))、长(size())。

 * */

public class TestList {

    //ArrayList:List的主要实现类

    @Test

    public void testList2() {

        ArrayList list=new ArrayList();

        list.add(123);

        list.add("AA");

        list.add(456);

        list.add("BB");

        list.add("AA");

        System.out.println(list.indexOf(456));

        System.out.println(list.indexOf(12));

       

        System.out.println(list.lastIndexOf("AA"));

       

        System.out.println(list.indexOf(123)==list.lastIndexOf(123));

       

        System.out.println(list.subList(1, 3));//左闭右开

    }

   

    @Test

    public void testList1() {

        ArrayList list=new ArrayList();

        list.add(123);

        list.add("AA");

        list.add(456);

        list.add("BB");

        System.out.println(list);

        list.add(0,666);//1、在指定位置处添加元素

        System.out.println(list);

        Object obj=list.get(3);//2、获取指定位置处的元素

        System.out.println(obj);

        //3、remove();--删除与指定位置的元素

        //4、set( , );--设置指定位置的元素为某某

    }

}

 

四、LinkedList类及Vector类的使用

1、ArrayList使用数组连接;而LinkedList则是使用链表联系在一起。(对于频繁的插入与删除操作建议选择用LinkedList)。

       2、Vector:古老的类,线程安全的;插入、删除等操作比较慢。

五、笔记总结:

 

 

                                             贰

                             Collection接口的Set子接口:无序的

Set接口:存储的元素是无序的,不可重复的!

      1、无序性:无序性!=随机性。真正的无序性,指的是元素在底层存储的位置是无序的。

         2、不可重复性:当向Set中添加进相同的元素时,后面的这个不能添加进去。

        3、如果要添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。

         进而保证Set中元素的不可重复性。

         4、如果要保存在Set中一定要重写Object类的equals()和hashCode()方法;如果要存储在List中则不需要重写hashCode方法。

         5、正因为Set中的元素是无序的,才用到了重写hashCode方法。

         6、Set中的元素是如何存储的呢?使用了哈希算法。

             当向Set中添加对象时,首先调用此对象所在的hashCode()方法,

        计算此对象的哈希值,此哈希值决定了此对象在Set中的存储位置。

        若此位置之前没有对象存储,则这个对象直接存储到此位置。

        若此位置已有对象存储,再通过equals()方法比较这两个对象是否相同。如果相同,后一个对象就不能再添加进来。

         6-万一返回false呢,都存储。(不建议这样)。

             >如果保存在Set中要求hashCode()方法一定要与equals()方法一致。

 

 

一、HashSet实例演示:

①、Person类:

package com.atguigu.collection;



public class Person {

    int id=1002;

   

   

    private String name;

    private int age;

    //有参的构造方法

    public Person(String name, int age) {

        super();

        this.name = name;

        this.age = age;

    }

    public Person() {  //无参的构造方法

        super();

    }

   

    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;

    }

    //自定义的函数

    public void walk() {

        System.out.println("人走路");

    }

    public void eat() {

        System.out.println("人吃饭");

    }

    @Override  //用于Set接口比较

    public int hashCode() {//1、return age.hashCode()+name.hashCode();没有下述的健壮性好。

        //2、建议直接用系统自动生成的。

        final int prime = 31;

        int result = 1;

        result = prime * result + age;

        result = prime * result + id;

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

//      3、return init++;//不建议这样用

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        Person other = (Person) obj;

        if (age != other.age)

            return false;

        if (id != other.id)

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

        return true;

    }

}

②、TestSet类:

package com.atguigu.collection;



import java.util.HashSet;

import java.util.Set;



import org.junit.Test;



/*

 * Collection接口

 *              |------List接口:存储有序的,可以重复的元素。List中常用的方法除了Colletion中的抽象方法在List子接口的类中实现的之外;还有自己特有的。

 *                     |----------ArrayList(主要的实现类)、LinkedList(对于频繁的插入、删除操作)、Vector

 *              |------Set接口:存储无序的不可重复的元素。Set中常用的方法都是Collection下定义的。

 *                     |----------HashSet(主要实现类)、

 *                                 LinkedHashSet、

 *                                 TreeSet

 *

 * */

public class TestSet {



    /*Set接口:存储的元素是无序的,不可重复的!

     * 1、无序性:无序性!=随机性。真正的无序性,指的是元素在底层存储的位置是无序的。

     * 2、不可重复性:当向Set中添加进相同的元素时,后面的这个不能添加进去。

     * 3、如果要添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。

     * 进而保证Set中元素的不可重复性。

     * 4、如果要保存在Set中一定要重写Object类的equals()和hashCode()方法;如果要存储在List中则不需要重写hashCode方法。

     * 5、正因为Set中的元素是无序的,才用到了重写hashCode方法。

     *

     *Set中的元素是如何存储的呢?使用了哈希算法。

     *  当向Set中添加对象时,首先调用此对象所在的hashCode()方法,

     *计算此对象的哈希值,此哈希值决定了此对象在Set中的存储位置。

     *若此位置之前没有对象存储,则这个对象直接存储到此位置。

     *若此位置已有对象存储,再通过equals()方法比较这两个对象是否相同。如果相同,后一个对象就不能再添加进来。

     * 万一返回false呢,都存储。(不建议这样)。

     * >要求hashCode()方法要与equals()方法一致。

     * */

    @Test

    public void testHashSet() {

        Set set=new HashSet();

        set.add(123);

        set.add("AA");

        set.add(new String("AA"));

        set.add(new String("AA")); //重新new的也不可以重复,两个重新new的和直接 .add("AA");三个只会显示一个"AA";

        set.add(456);

        set.add("BCD");

        set.add(null);

        Person p1=new Person("GG",23);

        Person p2=new Person("GG",23); //Person p2=new Person("MM",21); 

        /*

         * 如果上方为Person p1=new Person("GG",23);

         * 仍然结果与之前相同,因为这是两个对象,在Set比较二者时,

         * 调用的是equals方法,而在Person中没有重写equals方法,

         * 所以调用的是Object类中的equals方法,

         * Object类中的equals方法比较的是地址值是否相同

         */

       

        System.out.println(p1.equals(p2));

        System.out.println(p1.hashCode());

        System.out.println(p2.hashCode());

       

        set.add(p1);

        set.add(p2);

        System.out.println(set.size());

        System.out.println(set);

    }

}

二、LinkedHashSet的特点及实现:

图解:LinkedGHashSet在存储的时候是用链表的方式;不像数组那样通过下脚标可以找到相应的元素,而LinkedHashSet在用链表存储时没有下脚标,是无序的,但是却维护了添加进去的顺序。

1、LinkedHashSet是HashSet的子类。

2、LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。

3、LinkedHashSet插入性能略低于HashSet,但在迭代访问Set里的全部元素时有很好的性能。

4、LinkedHashSet不允许集合元素重复。

5、LinkedHashSet:使用链表维护了一个添加进集合中的顺序;导致当我们遍历LinkedHashSet集合元素时,是按照添加进去的顺序遍历的。

代码(LinkedHashSet):

public class TestSet {

    /*

     * LinkedHashSet:使用链表维护了一个添加进集合中的顺序。

     * 导致当我们遍历LinkedHashSet集合元素时,是按照添加进去的顺序遍历的。

     *

     * */

    @Test

    public void testLinkedHashSet() {

        Set set=new LinkedHashSet();

        set.add(123);

        set.add("I ");

        set.add(456);

        set.add("Love");

        set.add(new String("abc"));

        set.add(new String("abc"));

        set.add(new Person("MM",21));

        set.add(null);

       

        Iterator iterator=set.iterator();//迭代器

        while(iterator.hasNext()) {

            System.out.println(iterator.next());

        }

       

    }

}

三、TreeSet的自然排序:

TreeSet:

            1、向TreeSet中添加的元素必须是同一个类型的。

            2、可以按照添加进集合中的元素的指定顺序遍历。像String、包装类等默认按照从小到大的顺序遍历。

            3、当向TreeSet中添加自定义的对象时,有两种排序方法:①、自然排序;②、定制排序。当自然排序与定制排序混合在一起的话,以定制排序优先。

            4、自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法

         在此方法中,指明按照自定义类的哪个属性进行排序。

            5、向TreeSet中添加元素时,首先按照compareTo()方法进行比较,一旦返回0,虽然仅仅是两个对象的

         此属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来。

         

            >compareTo()与hashCode()以及equals()三者保持一致。

 

1、Person类:

package com.atguigu.collection;



public class Person implements Comparable{

    int id=1002;



    private String name;

    private Integer age;

    //有参的构造方法

    public Person(String name, int age) {

        super();

        this.name = name;

        this.age = age;

    }

    public Person() {  //无参的构造方法

        super();

    }

   

    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;

    }

    //自定义的函数

    public void walk() {

        System.out.println("人走路");

    }

    public void eat() {

        System.out.println("人吃饭");

    }

    @Override  //用于Set接口比较

    public int hashCode() {//1、return age.hashCode()+name.hashCode();没有下述的健壮性好。

        //2、建议直接用系统自动生成的。

        final int prime = 31;

        int result = 1;

        result = prime * result + age;

        result = prime * result + id;

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

//      3、return init++;//不建议这样用

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        Person other = (Person) obj;

        if (age != other.age)

            return false;

        if (id != other.id)

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

        return true;

    }

    //向TreeSet中添加Person类的对象时,依据此方法,确定按哪个属性排列。

    @Override

    public int compareTo(Object o) {

        if(o instanceof Person) {

            Person p=(Person)o;

//          return this.name.compareTo(p.name);//此处是按照name属性进行排序的。

//          return -this.age.compareTo(p.age);//加上负号表示由大到小

            //          return this.age.compareTo(p.age);//按照age进行排序(age是Integer类型的,Integer也实现了compareTo方法)。

//          自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法

//          在此方法中,指明按照自定义类的哪个属性进行排序。

//          为了使相同的也能写进TreeSet像数据库一样,有一级排序,一级排序相同再二级排序

           

            /*实现的是先按照age从小到大排,age相等按name排*/

            int i=this.age.compareTo(p.age);

            if(i==0) {//如果有age相等的则按名字排序

                return this.name.compareTo(p.name);

            }else {//如果age不等则按age排序

                return i;

            }

        }

        return 0;

    }

}

 

2、TestSet类中的testTreeSet()方法部分:

public class TestSet {

    /*

     * TreeSet:

     * 1、向TreeSet中添加的元素必须时同一个类型的。

     * 2、可以按照添加进集合中的元素的指定顺序遍历。像String、包装类等默认按照从小到大的顺序遍历。

     * 3、当向TreeSet中添加自定义的对象时,有两种排序方法:①、自然排序;②、定制排序。

     * 4、自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)方法

     * 在此方法中,指明按照自定义类的哪个属性进行排序。

     *

     * 5、向TreeSet中添加元素时,首先按照compareTo()方法进行比较,一旦返回0,虽然仅仅是两个对象的

     * 此属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来。

     *

     * >compareTo()与hashCode()以及equals()三者保持一致。

     * */

    @Test

    public void testTreeSet() {

        Set set=new TreeSet();

//      set.add(new String("AAA"));

//      set.add(new String("BBB"));

//      set.add("CD");

        set.add(123);  //TreeSet中添加的元素必须是同一个类型的,此处添加了两个int类型的。

        set.add(456);

//      set.add("EFG");

        /*当Person类没有实现Comparable接口时,当向TreeSet中添加Person对象时,报ClassCastException错误*/

        set.add(new Person("YY",24));

        set.add(new Person("XX",22));

        set.add(new Person("DD",21));/*在Person中对应实现的是先按照age从小到大排,age相等按name排*/

        set.add(new Person("TT",23));

        set.add(new Person("KK",23));

//      set.add("AA");出错(编译时不会有错,在真正运行时才会出错)因为和上面的类型不匹配

        for(Object str:set) {

            System.out.println(str);

        }

    }

}

 

四、TreeSet的定制排序:

 

1、Customer类的代码:

package com.atguigu.collection;



public class Customer {

    private String name;

    private int id;

    //Getters & Setters方法

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    //构造器

    public Customer(String name, int id) {

        super();

        this.name = name;

        this.id = id;

    }

    //toString方法

    @Override

    public String toString() {

        return "Customer [name=" + name + ", id=" + id + "]";

    }

    //hashCode & equals()方法

    @Override

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + id;

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        Customer other = (Customer) obj;

        if (id != other.id)

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

        return true;

    }

}

2、TestSet类中testTreeSet2()方法的代码:

public class TestSet {

    /*

     * TreeSet的定制排序:

     *      如下的1、2、3部。

     * compare()与hashCode()以及equals()三者保持一致。

     *

     * */

    @Test

    public void testTreeSet2(){

        //1、创建一个实现了Comparator接口的类对象

        Comparator com=new Comparator() {//Comparator中有equals和compare两个,但此处只是重写了compare,因为Comparator继承Object,Object中自动重写equals。

            //向TreeSet中添加Customer类的对象,在此compare()方法中,指明是按照Customer

            //的哪个属性排序的。上次的Person中是在compareTo()方法中写排序。

           

            @Override

            public int compare(Object o1, Object o2) {

                if(o1 instanceof Customer && o2 instanceof Customer) {

                   Customer c1=(Customer)o1;

                   Customer c2=(Customer)o2;

                   int i= c1.getId().compareTo(c2.getId());

//                 先按id排,id一样再按name排

                   if(i==0) {

                       return c1.getName().compareTo(c2.getName());

                   }else {

                       return i;

                   }

                }

                return 0;

            }

        };//不能缺少";"号

        //2、将此对象作为形参传递给TreeSet的构造器

        TreeSet set=new TreeSet(com);

        //3、向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象

        set.add(new Customer("AA",1003));

        set.add(new Customer("BB",1002));

        set.add(new Customer("GG",1004));

        set.add(new Customer("CC",1001));

        set.add(new Customer("DD",1007));

//      如果有两个id号一样的就只显示其中一个,另一个进不去

        for(Object str:set) {//遍历

            System.out.println(str);

        }

    }

}

五、TreeSet的使用练习:

1、当自然排序与定制排序混合在一起的话,以定制排序优先。

2、一般情况下,一个实体类中的多个对象如果按自然排序,需要实现重写Comparable接口;如果按定制排序,不需要实体类什么Comparable接口在创建TreeSet时需要传入Comparator对象格式如下:

Comparator com=new Comparator() {//先造一个Comparator接口实现类的一个对象

        @Override  //实现

        public int compare(Object arg0, Object arg1) {

            // TODO Auto-generated method stub

            return 0;

        }      

};

int型来定义的变量就不能调用compareTo()方法。

 

题目要求:

代码解析:

1MyDate类代码:

package com.atguigu.exec;



public class MyDate {

    private int day;

    private int month;

    private int year;

    public int getDay() {

        return day;

    }

    public void setDay(int day) {

        this.day = day;

    }

    public int getMonth() {

        return month;

    }

    public void setMonth(int month) {

        this.month = month;

    }

    public int getYear() {

        return year;

    }

    public void setYear(int year) {

        this.year = year;

    }

    public MyDate(int day, int month, int year) {

        super();

        this.day = day;

        this.month = month;

        this.year = year;

    }

    @Override

    public String toString() {

        return "MyDate [day=" + day + ", month=" + month + ", year=" + year + "]";

    }

    @Override

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + day;

        result = prime * result + month;

        result = prime * result + year;

        return result;

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        MyDate other = (MyDate) obj;

        if (day != other.day)

            return false;

        if (month != other.month)

            return false;

        if (year != other.year)

            return false;

        return true;

    }

}

2Employee类的代码:

package com.atguigu.exec;



public class Employee implements Comparable{

    private String name;

    private Integer age;

    private MyDate birthday;

    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;

    }

    public MyDate getBirthday() {

        return birthday;

    }

    public void setBirthday(MyDate birthday) {

        this.birthday = birthday;

    }

    public Employee(String name, int age, MyDate birthday) {

        super();

        this.name = name;

        this.age = age;

        this.birthday = birthday;

    }

    @Override

    public String toString() {

        return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]";

    }

   

    @Override

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + age;

        result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        Employee other = (Employee) obj;

        if (age != other.age)

            return false;

        if (birthday == null) {

            if (other.birthday != null)

                return false;

        } else if (!birthday.equals(other.birthday))

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

        return true;

    }

    @Override

    public int compareTo(Object o) {//只是按名字排序,并没写名字相同后按什么排序。

        if(o instanceof Employee) {

            Employee e=(Employee)o;

            return this.name.compareTo(e.name);

//          int i=this.name.compareTo(e.name);

//          if(i==0) {     /*  按照年龄从小到大 */

//              return this.age.compareTo(e.age);

//          }else {

//              return i;

//          }

        }

//      return 0;

        return 0;

    }

}

3Employee1类的代码:

package com.atguigu.exec;



public class Employee1{

    private String name;

    private Integer age;

    private MyDate birthday;

    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;

    }

    public MyDate getBirthday() {

        return birthday;

    }

    public void setBirthday(MyDate birthday) {

        this.birthday = birthday;

    }

    public Employee1(String name, int age, MyDate birthday) {

        super();

        this.name = name;

        this.age = age;

        this.birthday = birthday;

    }

    @Override

    public String toString() {

        return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]";

    }

    @Override

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + ((age == null) ? 0 : age.hashCode());

        result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());

        result = prime * result + ((name == null) ? 0 : name.hashCode());

        return result;

    }

    @Override

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        Employee1 other = (Employee1) obj;

        if (age == null) {

            if (other.age != null)

                return false;

        } else if (!age.equals(other.age))

            return false;

        if (birthday == null) {

            if (other.birthday != null)

                return false;

        } else if (!birthday.equals(other.birthday))

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

        return true;

    }

}

 

4、TestEmployee类的代码:

package com.atguigu.exec;



import java.util.Comparator;

import java.util.Iterator;

import java.util.TreeSet;



import org.junit.Test;



public class TestEmployee {

    //2、定制排序:创建TreeSet时传入Comparator对象

    @Test//按照生日的先后排序

    public void test2() {

         Comparator com=new Comparator() {//先造一个Comparator接口实现类的一个对象

            @Override  //实现

            public int compare(Object o1, Object o2) {

                if(o1 instanceof Employee1 && o2 instanceof Employee) {

                   Employee1 e1=(Employee1)o1;//向上转型

                   Employee1 e2=(Employee1)o2;

                   MyDate birth1=e1.getBirthday();

                   MyDate birth2=e2.getBirthday();

                   if(birth1.getYear() != birth2.getYear()) {

                       return birth1.getYear() - birth2.getYear();

                   }else{

                       if(birth1.getMonth() != birth2.getMonth()) {

                           return birth1.getMonth() - birth2.getMonth();

                       }else {

                               return birth1.getDay() - birth2.getDay();

                       }

                   }  

                }

                return 0;

            }

        };

        TreeSet set=new TreeSet(com);

        //之后就可以添加Employee1的实体类了

        Employee1 e1=new Employee1("刘德华", 55, new MyDate(4, 12, 1976));

        Employee1 e2=new Employee1("郭富城", 43, new MyDate(7, 3, 1954));

        Employee1 e3=new Employee1("张学友", 33, new MyDate(9, 3, 1954));

        Employee1 e4=new Employee1("黎明", 54, new MyDate(12, 2, 1954));

        Employee1 e5=new Employee1("李敏镐", 65, new MyDate(4, 21, 1945));

        set.add(e1);

        set.add(e2);

        set.add(e3);

        set.add(e4);

        set.add(e5);

   

        //遍历

        Iterator iterator=set.iterator();

        while(iterator.hasNext()) {

            System.out.println(iterator.next());

        }

    }

   

   

   

   

    // 1、自然排序:使Employee实现Comparable接口,并按name排序

    @Test

    public void test1() {

        Employee e1=new Employee("刘德华", 55, new MyDate(4, 12, 1976));

        Employee e2=new Employee("郭富城", 43, new MyDate(7, 3, 1965));

        Employee e3=new Employee("张学友", 33, new MyDate(9, 12, 1954));

        Employee e4=new Employee("黎明", 54, new MyDate(12, 2, 1967));

        Employee e5=new Employee("李敏镐", 65, new MyDate(4, 21, 1945));

        //下面的与上一条名字一样,后边信息都不同,但是加不进TreeSet中,

        //因为在Employee中重写的compareTo()方法里只用名字比较来完成排序。

        //如果要加进TreeSet中,在Employee的compareTo()方法中设置,先用名字排序,名字相同再用年龄或生日排序

        Employee e6=new Employee("李敏镐", 49, new MyDate(3, 2, 1993));



        TreeSet set=new TreeSet();

        set.add(e1);

        set.add(e2);

        set.add(e3);

        set.add(e4);

        set.add(e5);

        set.add(e6);

       

        //遍历

        Iterator iterator=set.iterator();

        while(iterator.hasNext()) {

            System.out.println(iterator.next());

        }

    }

//结果:按照姓名排,即姓的首字母a-b-c-d....

//Employee [name=刘德华, age=55, birthday=MyDate [day=4, month=12, year=1976]]

//Employee [name=张学友, age=33, birthday=MyDate [day=9, month=12, year=1954]]

//Employee [name=李敏镐, age=65, birthday=MyDate [day=4, month=21, year=1945]]

//Employee [name=郭富城, age=43, birthday=MyDate [day=7, month=3, year=1965]]

//Employee [name=黎明, age=54, birthday=MyDate [day=12, month=2, year=1967]]



   

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值