黑马程序员——Set接口

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
Set接口
1. Set的特点:
           元素无序,唯一。【注意和List的对比:元素有序(数据存储和取出顺序一致),可以重复】
            注意:这里顺序是指存储和取出顺序。
2 HashSet:
            (1).  HashSet:不保证元素的迭代顺序。并且,不保证该顺序恒久不变。
             (2).  怎么保证元素的唯一性?
                        --HashSet 底层数据结构是哈希表,它依赖两个方法:hashCode()、equals();
                        ①.  hashCode() :首先,判断hashCode()值是否相同。【该值默认源码是和地址值相关的所以不
                               可能相同了,进而判断不了重复(因为都是new出来的对象)】为了提高效率【如果重写
                               hashcod 直接返回一个0,就必须挨个的比较每个对象的属性值 效率低,而我们的hashcod
                               的本质是和成员的属性相关的,所以我的 hashcod值去所有元素的和字符串去 hashcod
                               的值。】 比如: return this.name.hashcod+this.age*13+his.score*17; 而*13/17是为了
                               让hashcod的值更准确的不相同了.
                        ②.  如果hashCode()的值相同了,继续走equals()方法,根据其返回值:来判断是否添加到集合。
                               --true:说明元素重复,不添加到集合。
                               --false:说明元素不重复,添加到集合。
                        ③.  怎么重写hashCode()和equals()方法呢?
                              -- hashCode():
                             把对象的所有成员变量值相加即可。如果是基本类型,就加值。如果是引用类型,就加哈希值。
                                  public int hashCode()
                                   {
                                             return this.name.hashCode() + this.age*13 + this.sex*17 +this.score*21;
                                    }
                              --equals():
                                      A:this==obj
                                      B:!(obj instanceof Student)
                                      C:所有成员变量的值比较。基本类型用==,引用类型用equals()。
                       ④. 如果不会,eclipse()自动生成。

             (3). HashSet 存储自定义对象
                           --创建HashSetDemo2类:
package testdemo;

import java.util.HashSet;

public class HashSetDemo2 {
	public static void main(String[] args) {
		// 创建集合对象
		HashSet<Student> hs = new HashSet<Student>();

		// 创建元素对象
		Student s1 = new Student("林青霞", 26);
		Student s2 = new Student("张曼玉", 36);
		Student s3 = new Student("周慧敏", 20);
		Student s4 = new Student("林青霞", 26);
		Student s5 = new Student("林青霞", 66);
		Student s6 = new Student("林志玲", 16);

		// 添加元素
		hs.add(s1);
		hs.add(s2);
		hs.add(s3);
		hs.add(s4);
		hs.add(s5);
		hs.add(s6);

		// 遍历
		for (Student s : hs) {
			System.out.println(s.getName() + "***" + s.getAge());
		}
	}
}
                           --创建创建自定义类Student:
package testdemo;

public class Student {
	private String name;
	private int age;

	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	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;
	}

	@Override
	//重写hashCode()方法.
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	//重写equals()方法
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}
                           --运行结果如下:

3.TreeSet
     (1)特点:

          a、底层结构是二叉树。按照树节点进行存储和取出。

          b、根据构造方法的不同,选择使用 自然排序 或者 比较器排序。按照实际的需求,可以对元素进行排

                序。并且保证唯一。

          c、原理:二叉树保证元素唯一 排序
                ①:第一个添加的数据作为根节点。
                :从第二个开始,每一个数据从根节点开始比较,如果大了,往右边放, 如果小了,往左边

                        放, 如果相同,替换。

                ③:原理图如下:


     (2)两种实现方式:

               ①、自然排序:(元素具备比较性)-------对象所属类实现comparable接口重写了接口中的比较方法,

                       而具有了比 较的功能,进而有了 "排序" 的功能。通过 TreeSet的无参构造,要求对象所属的

                       类实现 Comparable接口,重写comparable中的comparTo方法,定义自己的比较方法。

                       #重写compareTo()方法:

                       #this.是将要判断存入的元素,s已经在集合中存在的元素 [负数往前方,整数往s的后面放,0不存放]
                       #由于对象有多个成员变量,你不能根据其中的某一个决定其他的。
                       #因此 当某一个主要参数相同的时候,你还需要判断其他的是不是也是相同的。

                        public int compareTo( Studetn s )
                         {
                           // 需求:比较年龄
                                 int num = this.age - s.age ;     

                                //次要条件 :
                                  int num2 = ( num == 0 ) ? ( this.name.compareTo( s.name ) ) : num ;
                                  return num2;
                          }

               ②、比较器排序:(集合具备比较性)----通过构造方法,传入构造器(实现了comparable接口的对象),

                        而具有了比较的功能,进而具备了排序的功能
                        #TreeSet的带参构造,要求构造方法接收一个实现了Comparator接口的对象。如下:
                        TreeSet<Student> ts = new TreeSet<Student> ( new Comparator<Student> 
                        {
                             public int compare ( Student s1 , Student s2)
                              //其中s1是将要判断存入的元素,s2已经在集合中存在的元素[负数往前方,

                              整数往s2的后面放,0不存放]
                               {
                                      //按照年龄排序,从小到大
                                      int num = s1.getAge() - s2.getAge();
                                      //次要条件
                                       int num2 = ( num == 0 ) ? ( s1.getName().compareTo(s2.getName()) ) : num;
                                       return num2;
                                  }
                          } );

       (3)案例:TreeSet存储自定义对象按照姓名长度排序: 

                  ①、自然排序:(元素具备比较性)-------对象所属类实现comparable接口重写compareTo()

                  A:创建TreeSetDemo类:

package testdemo;
import java.util.TreeSet;

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

		// 创建TreeSet集合 ts.
		TreeSet<Student> ts = new TreeSet<Student>();

		// 创建并添加元素
		ts.add(new Student("刘德华", 52));
		ts.add(new Student("成龙", 60));
		ts.add(new Student("周星驰", 44));
		ts.add(new Student("孙燕姿", 34));
		ts.add(new Student("林青霞", 26));
		ts.add(new Student("林青霞", 36));
		ts.add(new Student("林青", 26));
		ts.add(new Student("林青霞", 26));

		// 遍历
		for (Student s : ts) {
			System.out.println(s.getName() + "***" + s.getAge());
		}
	}
}
                   B:创建 Student 类:

package testdemo;

public class Student implements Comparable<Student> {
	private String name;
	private int age;

	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	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;
	}

	@Override
	public int compareTo(Student s) {
		// 姓名的长度
		int num = this.name.length() - s.name.length();
		// 很多时候,别人给我们的需求其实只是一个主要需要
		// 还有很多的次要需求是需要我们自己进行分析的。
		// 比较姓名的内容
		int num2 = (num == 0) ? (this.name.compareTo(s.name)) : num;
		// 继续分析,姓名长度和内容都相同的情况下,年龄还可能不一样呢?
		// 所以,当姓名长度和内容都相同的时候,我们在比较下年龄就好了
		int num3 = (num2 == 0) ? (this.age - s.age) : num2;
		return num3;
	}
}
                   C:运行结果如下


                  ②、比较器排序(集合具备比较性)----通过构造方法,传入构造器(实现了comparable接口的对象)

                  A:创建TreeSetDemo类:

package testdemo;

import java.util.Comparator;
import java.util.TreeSet;

/*
 * 比较器接口 Comparator。带参构造。
 */
public class TreeSetDemo {
	public static void main(String[] args) {

		// 匿名内部类
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
			public int compare(Student s1, Student s2) {
				// 按年龄排序,从小到大
				int num = s1.getAge() - s2.getAge();
				// 次要条件
				int num2 = (num == 0) ? (s1.getName().compareTo(s2.getName())) : num;
				return num2;
			}
		});

		// 创建并添加元素对象
		ts.add(new Student("刘德华", 52));
		ts.add(new Student("成龙", 60));
		ts.add(new Student("周星驰", 44));
		ts.add(new Student("孙燕姿", 34));
		ts.add(new Student("林青霞", 26));
		ts.add(new Student("林青霞", 36));
		ts.add(new Student("林青", 26));
		ts.add(new Student("林青霞", 26));

		// 遍历
		for (Student s : ts) {
			System.out.println(s.getName() + "***" + s.getAge());
		}
	}
}

                   B:创建 Student 类:

package testdemo;

public class Student{
	private String name;
	private int age;

	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	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;
	}
}
                   C:运行结果如下































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值