php网站开发工程师任职要求,新开网站,搜索引擎优化的目的是什么,烟台广告公司网站建设Java的集合中主要由List#xff0c;Set#xff0c;Queue#xff0c;Map构成#xff0c;Set特点#xff1a;存取无序#xff0c;不可以存放重复的元素#xff0c;不可以用下标对元素进行操作。
HashSet
作为Set容器的代表子类#xff0c;HashSet经常被用到#xff0c…Java的集合中主要由ListSetQueueMap构成Set特点存取无序不可以存放重复的元素不可以用下标对元素进行操作。
HashSet
作为Set容器的代表子类HashSet经常被用到我们通过源码去分析它
public class HashSetEextends AbstractSetEimplements SetE, Cloneable, java.io.Serializable
{private transient HashMapE,Object map;// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT new Object();public HashSet() {map new HashMap();}public boolean add(E e) {return map.put(e, PRESENT)null;}public boolean remove(Object o) {return map.remove(o)PRESENT;}
}
虽然HashSet实现了Set接口但通过源码可以看到它的底层逻辑实现其实依据的是HashMap通过操作map的key值来实现元素的增删改查下面通过一个小测试类去用下HashSet。
public class Test {public static void main(String[] args) throws FileNotFoundException {// 创建一个新的HashSetHashSetInteger set new HashSet();// 添加元素set.add(3);set.add(4);set.add(0);set.add(1);set.add(4);// 输出HashSet的元素个数System.out.println(HashSet size: set.size());// 判断元素是否存在于HashSet中boolean containsWanger set.contains(2);System.out.println(containsWanger);// 删除元素boolean removeWanger set.remove(1);System.out.println(set);// 修改元素需要先删除后添加boolean removeChenmo set.remove(3);boolean addBuChenmo set.add(4);System.out.println(removeChenmo addBuChenmo);// 输出修改后的HashSetSystem.out.println(set);}
}
输出
HashSet size: 4
false
[0, 3, 4]
false
[0, 4]
由代码结果进一步证明了我们的结论1、存储数据不重复但add重复数据并不报错原因是第一个数据会被第二次重复数据覆盖掉2无序很多人发现输出了一个有序的数字集合这个其实与我们所说的有序是有区别的在Set中的有序无序是指输入的顺序与输出的顺序是否一致 当然想要实现有序可以通过LinkedHashSet底层通过链表记录元素插入顺序。
这里会有一个问题集合中的无序性和不可能重复性是什么意思 无序性所谓无序性不等于随机性也不等于输出无序就如同上面我们看到的向HashSet中随机添加数字输出是从大到小看似有序实际此序非彼序真正的无序性是指存储的数据在底层数组中并非按照数组索引的顺序添加 而是根据数据的哈希值进行判断。 不可重复性指添加的元素按照 equals() 判断时 返回 false因此实现不可重复性必须要同时重写 equals() 方法和 hashCode() 方法。
LinkedHashSet
那么就有一个问题“我就想存一个不重复的数据集合同时又想要他们有序怎么办呢”Java中用LinkedHashSet就可以解决了LinkedHashSet 是基于 LinkedHashMap 实现的并且使用链表维护了元素的插入顺序具有快速查找、插入和删除操作的优点又可以维护元素的插入顺序下面展示测试案例。
LinkedHashSetString set new LinkedHashSet();
// 添加元素
set.add(Hello);
set.add(Java);
set.add(Build);
set.add(Java);
System.out.println(set);
// 删除元素
set.remove(Hello);// 修改元素
set.remove(Java);
set.add(java);// 查找元素
boolean bool set.contains(Build);
System.out.println(哈喽: bool);//输出
System.out.println(set);
输出
[Hello, Java, Build]
哈喽:true
[Build, java]
通过输出结果我们可以得出结论LinkedHashSet中的元素不可重复有序。
TreeSet
通过上面两个集合类我们大概能够猜到几乎所有的Set集合的底层都是通过Map去实现TreeSet同样是基于TreeMap实现TreeMap 基于红黑树实现所以TreeSet也就自带了排序功能。 public TreeSet() {this(new TreeMapE,Object());}示例
public class Test {public static void main(String[] args) {// 创建一个 TreeSet 对象TreeSetInteger set new TreeSet();set.add(3);set.add(6);set.add(2);set.add(1);set.add(0);set.add(9);System.out.println(set);}
}
输出
[0, 1, 2, 3, 6, 9]
总结 HashSet、LinkedHashSet 和 TreeSet 都是 Set 接口的实现类都能保证元素唯一并且都不是线程安全的。 HashSet、LinkedHashSet 和 TreeSet 的主要区别在于底层数据结构不同。HashSet 的底层数据结构是哈希表基于 HashMap 实现。LinkedHashSet 的底层数据结构是链表和哈希表元素的插入和取出顺序满足 FIFO。TreeSet 底层数据结构是红黑树元素是有序的排序的方式有自然排序和定制排序。 底层数据结构不同又导致这三者的应用场景不同。HashSet 用于不需要保证元素插入和取出顺序的场景LinkedHashSet 用于保证元素的插入和取出顺序满足 FIFO 的场景TreeSet 用于支持对元素自定义排序规则的场景。 此外HashSet、LinkedHashSet允许有 null 值TreeSet不允许有null值当向 TreeSet 插入 null 元素时TreeSet 使用 compareTo 方法与 null 元素进行比较报错java.lang.NullPointerException。