zoukankan      html  css  js  c++  java
  • 集合框架__【Set集合】【HashSet】【TreeSet】



    Set:元素是无序的,不能重复
    Set集合的功能和Collection是一致的,无特有方法
    ————HashSet:底层数据结构是哈希表
    ————TreeSet:底层数据结构是二叉树

    HashSet

    HasnSet 通过equals方法和hashCode方法来保证元素的唯一性
    ———— 如果hashCode相同,还要调用equals判断元素是否相同
    ———— 如果hasnCode不同,就不用判断equals
    ————HashSet方法中的元素是按照哈希表来存储的,所以打印的时候不是无序的

    在hashSet中对元素contains、remove等操作时,先判断hashCode,再判断equals
    而在ArrayList中对元素的操作只依赖于equals方法

    所以HashSet时一般都要覆盖hashCode方法和equals方法

    示例:往HashSet集合中存入自定义对象,姓名年龄相同则视为同一个元素

    HashSet示例

    在Person类中覆盖

    	public int hashCode()//覆盖hashCode方法
    	{
    		System.out.println(this.name+"........hashCode.");
    		return name.hashCode()+age*22;	//*22是为了保证哈希值的唯一性
    	}
    	public boolean equals(Object obj)//在对象中复写equals方法
    	{
    		if (!(obj instanceof Person))	//健壮性判断;一元运算符!要加括号
    			return false;
    		Person p = (Person)obj;		//类型向下强转
    		System.out.println(this.name+"..equals.."+p.name);
    		return this.name.equals(p.name) && this.age==p.age;//字符串的equals方法
    	}
    主函数中的操作:

    		HashSet ha = new HashSet();
    		ha.add(new Person("hs1",21));
    		ha.add(new Person("hs2",22));//每new一个对象,就分配一个不同的哈希值
    	//	ha.add(new Person("hs2",22));//哈希值不同,就执行不到equals
    		ha.add(new Person("hs3",23));
    
    		sop("hs1:"+ha.contains(new Person("hs1",21)));//判断是否存在
    
    		Iterator it = ha.iterator();
    		while (it.hasNext())
    		{
    			Person p = (Person)it.next();
    			sop(p.getName()+"..."+p.getAge());
    		}


    TreeSet

    TreeSet:对Set集合元素进行排序。而元素必须具有比较性才能排序

    ——TreeSet底层数据结构是二叉树,位置是由compareTo的返回值决定的
    ——可以通过控制返回值来控制二叉树元素位置
    ——保证元素唯一性的依据是:compareTo方法return 0

    ①TreeSet排序的第一种方式:让元素自身具备比较性,

    ——元素需实现Comparable接口,覆盖compareTo方法,这种方式称为元素的自然(默认)排序

    Comparable接口

    ——强行对实现它的每个类对象进行整体排序,称为类的自然排序
    ——唯一的compareTo()方法
    ——返回正数0负数
    排序时,当主要条件相同时,要判断次要条件,否则元素无法存入


    ②TreeSet排序的第二种方式:元素不具备比较性,或者具备的比较性不能满足需要
    这时就让集合具备比较性
    集合在初始化时,就具备了比较方式

    定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数

    Comparator接口

    具备compare()和equals两个方法

    使用方式:定义一个类,实现Comparator接口,覆盖compare方法


    使用示例

    class TreeSetDemo2
    {
    	public static void sop(Object obj)
    	{
    		System.out.println(obj);
    	}
    
    	public static void main(String[] args) 
    	{
    		TreeSet ts = new TreeSet(new MyCompare());	//
    		ts.add(new Student("set 1",22));
    		ts.add(new Student("set 8",18));
    		ts.add(new Student("set 3",23));
    		ts.add(new Student("set 7",33));
    		ts.add(new Student("set 5",33));
    
    		Iterator it = ts.iterator();
    		while (it.hasNext())
    		{
    			Student st = (Student)it.next();
    			sop(st.getName()+"..."+st.getAge());
    		}
    	}
    }
    class Student implements Comparable
    {
    	private String name;
    	private int age;
    
    	Student(String name, int age)
    	{
    		this.name = name;
    		this.age = age;
    	}
    	public int compareTo(Object obj)	//实现compareTo方法
    	{
    		if (!(obj instanceof Student))	//健壮性判断
    			throw new RuntimeException("不是学生");//RunTime异常
    		Student s = (Student)obj;		//向下转型
    	//	System.out.println(this.name+"..compareTo.."+s.name);
    
    		int x = this.age-s.age;
    		int n = this.name.compareTo(s.name);//String类中已经实现了Comparable接口,返回值为int	
    		if (x==0)
    		{
    			return n;
    		}
    		return x;
    	}
    	public String getName()
    	{
    		return name;
    	}
    	public int getAge()
    	{
    		return age;
    	}
    }
    
    class MyCompare implements Comparator	//比较器,按照姓名排序
    {
    	public int compare(Object o1, Object o2)
    	{
    		Student s1 = (Student)o1;	//向下转型
    		Student s2 = (Student)o2;
    
    		int n = s1.getName().compareTo(s2.getName());//String类的compareTo
    		int x = s1.getAge() - s2.getAge();
    		if (n==0)
    		{
    			return x; 
    		}
    		return n;
    	}
    }

    小练习:使字符串按照长度从短到长排序

    class StringLengthComparator implements Comparator	//比较器
    {
    	public int compare(Object o1,Object o2)
    	{
    		String s1 = (String)o1;
    		String s2 = (String)o2;
    
    	//	int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));//compareTo是对象之间的比较
    		int num = s1.length() - s2.length();
    		if (num==0)
    			return s1.compareTo(s2);
    		return num;
    	}
    }


    【小结:Comparable和Comparator的区别

    二者都是接口,需要被实现,但是Comparable是被对象实现,comparator是被比较器实现

    Comparable 是一个对象本身就已经支持自比较所需要实现的接口,(如 String、Integer 等数据类对象自己就可以完成比较大小操作,已经实现了Comparable接口)可以直接使用CompareTo()方法进行比较;而一般对象需要继承该接口,实现compareTo()方法后才能然后完成比较。如Student类需要继承Comparable接口

    Comparator可以看成一种算法的实现,将算法和数据分离; 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。将比较器对象传入TreeSet的构造函数来调用

    简单来说:一个是自已完成比较,一个是外部程序实现比较。
    当两种排序都存在时,以比较器为主,因为Comparator的使用更加灵活,不需要对对象进行修改




  • 相关阅读:
    C. Shaass and Lights 解析(思維、組合)
    D. Binary String To Subsequences(队列)(贪心)
    CodeForces 1384B2. Koa and the Beach (Hard Version)(贪心)
    CodeForces 1384B1. Koa and the Beach (Easy Version)(搜索)
    CodeForces 1384C. String Transformation 1(贪心)(并查集)
    CodeForces 1384A. Common Prefixes
    POJ-2516 Minimum Cost(最小费用最大流)
    POJ3261-Milk Patterns(后缀数组)
    HDU-1300 Pearls(斜率DP)
    HDU-4528 小明系列故事-捉迷藏(BFS)
  • 原文地址:https://www.cnblogs.com/Joure/p/4337223.html
Copyright © 2011-2022 走看看