Java语法基础学习DayTen(集合续)

一、集合

1.Set:存储的元素是无序的、不可重复的

(1)无序性:无序性不等于随机性,无序指的是元素在底层存储的位置是无序的。

(2)不可重复性:当向Set中添加相同的元素时,后添加的元素不能添加进去;要求添加进Set的元素所在的类,一定要重写equals()方法和hashCode()方法,从而保证Set中元素的不可重复。 

(3)Set中的元素如何存储——哈希算法

  当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算该对象的哈希值,此哈希值决定了对象在Set中的存储位置。若此位置之前没有对象存储,则这个对象直接存储到此

位置,若已存在对象,在通过equals()方法比较这两个对象是否相同。

  注意:hashCode()和equals()方法要保持一致性,即两个对象通过equals比较的结果是不同,它们通过hashCode()方法得到的哈希值也应该不同。

  下面是自定义类Person中的hashCode()方法代码:

class Person{
    private String name;
    private Integer age;
      
    @Override
    public int hashCode(){
        //return age.hashCode()+name.hashCode();这种方法没有下述的方法的健壮性好
        final int prime = 31;//31是个质数
        int result = 1;
        result = prime * result + ((age == null)? 0:age.hashCode());
        result = prime * result + ((name == null)? 0:name.hashCode());//使用了迭代的方法,等号右边的result是上面式子得到的结果。
        return result;
    }
}

2.LinkedHashSet:使用链表维护了元素添加进集合的顺序,使得元素看起来是以插入的顺序保存的(实际存储是无序的)

(1)特点

  LinkedHashSet插入性能略低与HashSet,但在迭代访问Set里的所有元素有很好的性能。(有链表作为索引)

3.TreeSet

(1)特点

A:向TreeSet中添加的元素必须是同一个类的。

B:可以按照添加进集合中的元素的指定的顺序遍历。像String,包装类等默认按照从小到大的顺序遍历,如String按“ABCD...”的顺序。

Set set = new TreeSet();
set.add(new String("AA"));
set.add(new String("JJ"));
set.add(new String("MM"));
set.add(new String("GG"));
set.add(new String("BB"));

for(Object obj: set){
    System.out.println(obj);//按英文顺序输出AA,BB,GG,JJ,MM
}

C:当向TreeSet中添加自定义类的对象时,有两种排序方法:自然排序;定制排序

D:自然排序:要求自定义类实现java.lang.Comparable接口并重写其CompareTo(Object obj)的方法,在此方法中指明按自定义类的哪种属性进行排序。

   向TreeSet添加元素时,首先按照compareTo()进行比较,一旦返回0,虽然只是进行比较的两个属性值相同,但程序会认为这两个对象相同,后一个对象不能添加进来,所以要保证

compareTo()与hashCode()以及equals()的一致性。

class Person implements Comparable{
    private String name;
    private Integer age;
    @Override
    public int compareTo(Object obj){
        if(obj instanceof Person){
            Person p = (Person)obj;
            int i = this.age.compareTo(p.age);
            if(i == 0){
                return this.name.compareTo(p.name);
            }else{
                return i;//返回值加一个负号则顺序按从大到小排列
            }
        }
        return 0;
    }
}

public void test(){
    
    Set set = new TreeSet();
    //当Person类没有实现Comparable接口时,向TreeSet添加Person对象,会报ClassCastException
    set.add(new Person("AA"16));
    set.add(new Person("JJ"13));
    set.add(new Person("MM"14));
    set.add(new Person("GG"16));
    set.add(new Person("BB"12));
    for(Object obj: set){
        System.out.println(obj);//Person[name=BB,age=12],Person[name=JJ,age=13],Person[name=MM,age=14],
                                //Person[name=AA,age=16],Person[name=GG,age=16]
    }
}

 E:定制排序:要保证compare()与hashCode()以及equals()的一致性。

public void test(){
    //1.创建一个实现了Comparator接口的类对象
    Comparator com = new Comparator(){
        //向TreeSet中添加Person类的对象,在此compare()方法中,指明按照Person的哪个属性排序
        @Override
        public int compare(Object obj1,Object obj2){
            if(obj1 instanceof Person && obj2 instanceof Person){
                Person p1 = (Person)obj1;
                Person p2 = (Person)obj2;
                int i = p1.getAge().compareTo(p2.getAge());
                if(i == 0){
                    return p1.getName().compareTo(p2.getName());
                }else{
                    return i;
                }
            }
        return 0;
        }    
    }
    //2.将此Comparator对象作为形参传递给TreeSet的构造器中
    TreeSet set = new TreeSet(com);
    //也可以直接在形参创建匿名的Comparator对象
    //    TreeSet set = new TreeSet(new Comparator(){
    //        public int compare(Object o1,Object o2){
    //            比较的代码
    //        }    
    //    });
    //3.向TreeSet中添加Comparator接口中的compare()方法涉及的类的对象
    set.add(new Person("AA"16));
    set.add(new Person("JJ"13));
    set.add(new Person("MM"14));
    set.add(new Person("GG"16));
    set.add(new Person("BB"12));
}

猜你喜欢

转载自www.cnblogs.com/lsf2576/p/10526986.html