Java集合之Set

interface Set

  • 无序、无下标、元素不能重复(当插入新元素时,会调用euqals进行比较)
  • 方法:全部继承自Collection中的方法
  • Set集合继承Collection接口,方法全部来自Collection接口,自身没有定义其他方法。
  • Set接口主要两个实现类为HashSet、TreeSet。
  • Set集合中的元素不按特定顺序排序。因此无法向list一样根据索引获取数据。
  • 引用到堆上同一个对象的两个引用是相等的。如果对两个引用调用hashCode方法,会得到相同的结果,如果对象所属的类没有覆盖Object的hashCode方法的话,hashCode会返回每个对象特有的序号(java是依据对象的内存地址计算出的此序号),所以两个不同的对象的hashCode值是不可能相等的。

Set下几个重要的实现类与接口

  • HashSet(类)
  • LinkedHashSet(类)
  • SortedSet(接口)下的TreeSet(class )
- Class HashSet【重点】:
  • 存取HashSet集合中的元素,是根据哈希码来存取。HashSet根据哈希码来确定元素在集合中存储的位置(内存地址)
  • HashSet不能保证迭代顺序,且允许元素为null
  • 比较两个HashSet集合是否相同,先比较hasCode()返回的值是否相同,在使用equals()方法比较两个HashSet存储位置是否相同。如果满足以上两个条件,则HashSet集合相同。
  • hasCode()和equals()方法必须一起使用,以保证判断HashSet一致性。
  • 无参构建初始容量16 和负载因子0.75
  • 线程不安全,存取速度快。底层是以hash表实现的。
public class TestHashSet{
	public static void main(String[] args){
		HashSet<String> hashset = new HashSet<String>();
		hashset.add("中国");
		hashset.add("美国");
		hashset.add("日本");
		hashset.add("英国");
		System.out.println(hashset.add("中国")); // 输出false 不重复
		//System.out.println(map);
		//清空HashSet中的所有元素
		//hashset.clear();
		System.out.println(hashset);
		//删除指定名称的元素
		hashset.remove("日本");
		System.out.println(hashset);
		//使用迭代器遍历HashSet中的所有元素
		Iterator iterator = hashset.iterator(); 
           while (iterator.hasNext()){
                 System.out.println("遍历HashSet中的所有元素: "+iterator.next());  
              }
        //获取HashSet集合中的元素个数
        hashset.size();
	}
}
  • HashSet如何去重
    1)HashSet底层使用的是HashMap类,即是使用
    ctrl+shift+o快速导入包
    哈希码不唯一,两个不同对象,巧合版的哈希码相同,HashSet怀疑两个对象对不对就是相同对象,调用
    当存入元素的哈希码相同时,会调用equals进行确定,如结果为true,则拒绝后者存入
    HashCode比较是否相同,如果相同,表示可能是重复对象,先调==再调equals
    euqals二次确认
LinkedHashSet:
  • 底层使用LinkedHashMap(链表结构)存储,按照链表进行存储,既可保留元素的插入顺序
  • LinkedHashSet 是 Set 的一个具体实现,其维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
  • LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的。
  • 如果需要迭代的顺序为插入顺序或者访问顺序,那么 首先考虑LinkedHashSet
  • 除了内部存储,可保留元素的插入顺序以外使用方法与HashSet没什么区别
Interface SortedSet
class TreeSet
  • 实现了SortedSet接口,要求必须可以对元素排序。
  • 所有插入元素,必须实现Comparab方法mpareTofangfa
  • 根据compareTo方法返回0作为去重的依据,(意味重复)
  • TreeSet集合中的元素是有顺序的,如果要排序直接使用TreeSet
  • TreeSet的使用和其他集合差不多
  • 红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。
    红黑树算法的规则: 左小右大。
import java.util.TreeSet;
public class TestTreeSet {

    public static void main(String[] args) {

        TreeSet<String> tsb=new TreeSet();
        tsb.add("张三");
        tsb.add("李四");
        tsb.add("王五");
        tsb.add("赵六");
        tsb.add("黑七");
        System.out.println("树集合"+tsb);
        System.out.println("树集合的第一个元素"+tsb.first());
        System.out.println("树集合最后一个 元素"+tsb.last());
        System.out.println("头(李四)"+tsb.headSet("李四"));
        System.out.println("尾(李四)"+tsb.tailSet("李四"));
        System.out.println("ceiling(四)"+tsb.ceiling("四"));
        // 遍历迭代
        Iterator<String> iterator = tsb.iterator();
          while (iterator.hasNext()){
             System.out.println(iterator.next());
          }
       }
}

既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

1:让存入的元素自定义比较规则。

2:给TreeSet指定排序规则。

方式一:元素自身具备比较性

元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

方式二:容器具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)

通过return 0来判断唯一性。

因为字符串实现了一个接口,叫做Comparable 接口,所以字符串默认输出是按升序排列字符串重写了该接口的compareTo 方法,所以String对象具备了比较性.那么同样道理,我的自定义元素(例如Person类,Book类)想要存入TreeSet集合,就需要实现该接口,也就是要让自定义对象具备比较性.

存入TreeSet集合中的元素要具备比较性.

比较性要实现Comparable接口,重写该接口的compareTo方法

TreeSet属于Set集合,该集合的元素是不能重复的,TreeSet如何保证元素的唯一性

通过compareTo或者compare方法中的来保证元素的唯一性。

添加的元素必须要实现Comparable接口。当compareTo()函数返回值为0时,说明两个对象相等,此时该对象不会添加进来。

比较器接口

----| Comparable
compareTo(Object o) 元素自身具备比较性
----| Comparator
compare( Object o1, Object o2 ) 给容器传入比较器

TreeSet集合排序的两种方式:
一、让元素自身具备比较性。
也就是元素需要实现Comparable接口,覆盖compareTo 方法。
这种方式也作为元素的自然排序,也可称为默认排序。
二、让容器自身具备比较性,自定义比较器。

  • 定义一个类实现Comparator 接口,覆盖compare方法。
  • 并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。
  • 当Comparable比较方式,及Comparator比较方式同时存在,以Comparator比较方式为主。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: HashSetJava中的一种集合类型,它继承自AbstractSet类,并且实现了Set接口。它是基于哈希表实现的,可以存储不重复的元素。HashSet的实现依赖于它存储的元素的hashCode()方法和equals()方法。 当一个元素被添加到HashSet中时,HashSet会首先调用该元素的hashCode()方法,然后根据hashCode()方法的返回值,将该元素放入相应的桶(bucket)中。如果桶中已经存在该元素,则HashSet会调用该元素的equals()方法与桶中的元素进行比较,如果equals()方法返回true,表示这两个元素是相同的,HashSet就不会再次添加该元素。如果equals()方法返回false,则HashSet会将该元素添加到桶中。 由于HashSet是基于哈希表实现的,所以它的查询速度非常快,平均时间复杂度为O(1)。但是,HashSet的迭代顺序并不是按照元素的插入顺序来排列的,而是按照元素的哈希值来排列的。 ### 回答2: HashsetJava集合框架中的一种集合类,它基于哈希表实现,也称为哈希集。与List相比,Hashset集合中的元素不是有序的,而是无序的。而且,Hashset集合中的元素是唯一的,即集合中不存在相同的元素。 哈希表是哈希算法的一种典型应用,Hashset底层通过哈希表来实现。具体来说,当往Hashset中添加元素时,Hashset会先对这个元素进行哈希运算,根据哈希算法得到一个唯一的哈希值。这个哈希值会被作为元素在哈希表中的位置来存储。如果这个位置上已经有其它元素了,那么Hashset会比较这个元素和已存在元素的哈希值和equals()方法,若哈希值相同且equals()方法返回true,则认为这个元素已经存在于集合中,不再添加;否则,哈希表会使用开链的方式在这个位置上存储多个元素。 由于哈希表是一种效率比较高的数据结构,因此Hashset在添加、删除和查找元素时的速度都比较快。但是,由于哈希表的实现依赖于哈希算法的效率,哈希表在存储元素时可能会发生哈希冲突,导致性能下降。通常情况下,为了避免哈希冲突的发生,我们需要根据实际情况来选择合适的哈希函数或者调整哈希表的大小。 总之,Hashset作为Java集合框架中的一种集合类,提供了高效的添加、删除和查找元素的操作,同时也会遇到哈希冲突的问题需要注意。 ### 回答3: Java集合类中的Set是一个不允许有重复元素的集合。而HashSet则是Set接口的一种具体实现,底层实现采用的是哈希表,因此插入、删除和查找的时间复杂度均为O(1)。 HashSet中的元素并没有被排序,因为它是基于哈希表实现的。哈希表通过将元素的关键字映射到数组的索引位置来实现快速访问,即使将大量元素存储在哈希表中,访问元素时仍然能够在常数时间内完成。 HashSet中元素是根据它们的哈希码值存储的,因此先要实现hashCode()方法。此外,还要实现equals()方法来确保HashSet能够正确地判断两个元素是否相等。当两个元素的hashCode()值相等并且equals()方法返回true时,HashSet将认为这两个元素是相同的,不会插入重复元素。 HashSet的迭代器是一种散列码的迭代器,它返回的元素不会保证按照任何特定的顺序排列。当遍历HashSet时,不能保证元素的迭代顺序与元素插入的顺序相同。 在使用HashSet时需要注意,由于哈希表的实现,HashSet不是线程安全的,如果多个线程同时访问HashSet,可能会导致意外的结果,需要进行同步处理。 总之,HashSet是一个高效的集合实现,它允许快速的插入、删除和查找。如果你需要一个不允许重复元素的无序集合,并且希望能够快速地访问和修改元素,那么HashSet是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值