黑马程序员----JAVA----集合小结(Set)

来源:互联网 发布:ftp网络错误10053 编辑:程序博客网 时间:2024/06/13 23:44

----------------------------------android培训、java培训、期待与您交流!------------------------------

 

 

Set与Collection的关系

           Set是一种Collection,即Set接口是Collection接口的子接口。

Set:元素是无序的(存入和取出的顺序不一致),元素是不可以重复的。

       HashSet:底层数据结构使用的是哈希表。线程不同步;

 

HashSet是如何保证元素的唯一性的呢?

       是通过元素的两个方法:hashcode和equals来完成的。

       先比较hashcode(),在使用equals()比较。

       如果hashCode()相等,再使用equals()比较;如果hashCode()不相等,那么就不再使用equals()比较了。

       如果两个对象的equals()比较为true,那么hashCode()必须相同。

       例如:Person比较的是两个对象的nameagesex

       那么hashCode()使用nameagesexhashCode()相加,这就能保存上面的条件了。基本类型就本身也就可以了,要么也可以转换成对应的包装器类型,再去获取hashCode()

 

添加元素的流程:

当把元素添加到哈希表中时,需要先找到元素对应的桶位,然后判断这个桶中是否存在这个元素,如果元素在桶中已经存在,那么添加失败;否则添加成功!

 获取元素的哈希码值(使用元素的hashCode()方法);

 通过哈希码值计算桶位(可以把哈希码值理解为就是桶位);

 遍历桶中元素,使用元素的equals()方法,验证元素是否在桶中已经存在;

 存在则添加失败,否则把元素添加到桶中。

 

添加元素的问题:

HashSet<Person> set = new HashSet<Person>();

Person p1 = new Person(“zhangSan”, 23, “male”);

Person p2 = new Person(“zhangSan”, 23, “male”);

set.add(p1);

set.add(p2);

上面代码中set.add(p2)的结果会添加成功!也就是说HashSet会认识p1p2是两个不同对象。如果想让上面代码中set.add(p2)添加失败,我们需要让HashSet认为p1p2是相等的。

set.add(p2):调用p2hashCode()方法获取哈希码,通过哈希码找到桶。如果p1p2hashCode()不同,那么p2找到的桶就与p1找到的桶不同。

循环遍历p2对应桶中所有元素,使用equals()比较,如果没有相同元素,那么添加p2到这个桶中。

结论:就算p1.equals(p2)结果为true,但p1.hashCode() != p2.hashCode(),那么也是枉然!

 

LinkedHashSetHashSet的子类

      LinkedHashSetHashSet的子类,也就是说LinkedHashSet底层也使用的是哈希表!

      LinkedHashSet的迭代顺序是添加顺序!因为内部使用了链表来记录元素的添加顺序,迭代时再使用添加时顺序迭代!

 

TreeSet:     

     TreeSet是有序的,它会把元素排序,但如果元素没有自然顺序,那就出错。

     要求元素类型,必须去实现Comparable接口。这个接口只有一个方法:

     compareTo(T o),用来比较当前对象与参数对象谁大谁小。this > o,返回一个正数;this < 0,返回一个负数;否则返回0

     TreeSetcompareTo()方法保证元素的唯一性,如果新添加的元素,与当前Set中的元素使用compareTo比较结果为0,那么就说明元素已经存在,再添加就重复了,所以添加失败!

 

TreeSet特性:

    不同步,即线程不安全      有序,无重复元素(所有的Set都有这个特性);

    底层使用的是二叉树结构

 

TreeSet是怎么保证元素唯一性的?

要求元素具有可比性!

例如:数值类型都具有可比性:10 > 3

例如:String类型具有可比性:”abc”.compareTo(“def”) < 0

但是,Person没有可比性。

任何实现了Comparable接口的类都是具有可比性的!

当两个元素使用compareTo()方法比较返回0时,表示两个元素是相同的!

/*

     演示CompareTo方法

*/

//创建一个类

public class ComparableDemo {
       public static void main(String[] args) {

             //创建集合对象
             TreeSet<Person> ts=new TreeSet<Person>();
             Person p1=new Person("changsan","male",32);
             Person p2=new Person("bisi","male",22);
             Person p3=new Person("aangwu","female",12);

             //添加元素
             ts.add(p1);
             ts.add(p2);
             ts.add(p3);

            //遍历集合中的元素
            for(Person p:ts){
                  System.out.println(p);
             }
  
 }

}

//实现Comparable接口

public class Person implements Comparable<Person> {


       private String name;
       private String sex;
       private int age;
 public Person(String name, String sex, int age) {
        super();
        this.name = name;
        this.sex = sex;
        this.age = age;
 }
 public Person() {
       super();
 }


 @Override
 public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + age;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      result = prime * result + ((sex == null) ? 0 : sex.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;
      Person other = (Person) obj;
      if (age != other.age)
          return false;
      if (name == null) {
      if (other.name != null)
          return false;
         } else if (!name.equals(other.name))
           return false;
       if (sex == null) {
       if (other.sex != null)
             return false;
        } else if (!sex.equals(other.sex))
            return false;
             return true;
 }
 @Override
 public String toString() {
  return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getSex() {
  return sex;
 }
 public void setSex(String sex) {
  this.sex = sex;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 
 @Override

public int compareTo(Person p) {

      int n = name.compareTo(p.name);

      if(n != 0) {

         return n;

   }

      n = age - p.age;

      if(n != 0) {

         return n;

   }

      return sex.compareTo(p.sex);

   }

上面代码先是比较两个对象的name,如果name可以分出大小,那么就返回结果;

如果name分不出大小,那么再去比较年龄,如果年龄分出大小,那么就返回结果;

如果年龄再分出不结果,那么最终以性别来比较。

 

 

//定义一个类实现Comparator接口,做个比较器

public class ComparatorDemo {
         public static void main(String[] args) {
                      //创建一个内部类的接口比较器
                  TreeSet<Person> ts=new TreeSet<Person>(new Comparator<Person>(){

                       @Override
                      //重写compare 方法
                      public int compare(Person p1, Person p2) {
                     //获取p1对象的性别
                     /**/String str1=p1.getSex();
                     //获取p2对象的性别
                      String str2=p2.getSex();
                          //让他们进行比较如果对象1等于男,如果对象2等于女 就返回1,将当前对象返回。
                          //否则对象1等于女,如果对象2等于男,就返回-1,将当前对象返回。
                     if(str1.equals("male")){
                                 if(str2.equals("female")){
                                           return 1;
                     }
                             }else{
                                 if(str2.equals("male"));
                                return -1;
    }
                        //比较年龄
                   /**/int i=p1.getAge()-p2.getAge();
                              i f(i!=0){
                                   return i;
                      }
                           //比较姓名
                    return p1.getName().compareTo(p2.getName());
               }
   
  });
                      //将Perosn对象添加到集合中
                      ts.add(new Person("changsan","male",32));
                      ts.add(new Person("bisi","female",22));
                      ts.add(new Person("aangwu","male",22));
                      //创建接口的迭代器
                      Iterator<Person> it=ts.iterator();
                      //遍历集合中的元素
                      while(it.hasNext()){
                           System.out.println(it.next());
                   }
           }
}

 

     

----------------------------------android培训、java培训、期待与您交流!------------------------------

原创粉丝点击