JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序
Posted 所得皆惊喜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序相关的知识,希望对你有一定的参考价值。
文章目录
- ①. HashSet的概述
- ②. 哈希值的介绍
- ③. LinkedHashSet存取有序
- ④. TreeSet - 排序
- ⑤. 自然顺序(Comparable)
- ⑥. 比较器顺序(Comparator)
- ⑦. 两种排序比较
①. HashSet的概述
-
①. 无序性!=随机性(正在的无序性是指元素在底层存储的位置是无序的)
-
②. 不可重复性:当向set中添加进相同的元素的时候,后面的这个不能添加进去
-
③. 没有带索引的方法,所以不能用普通for循环遍历
-
④. 底层数据结构是哈希表
HashSet<String>hs=new HashSet<>();
boolean b1=hs.add("a");
boolean b2=hs.add("a");
hs.add(null);
//[null, a]
System.out.println(hs); //HashSet的继承体系中,有重写toString()方法
System.out.println(b1);//true
System.out.println(b2);//false
//只要能用迭代器迭代的,就可以使用增强for循环遍历
for(String str:hs)
System.out.println(str);//[null,a]
②. 哈希值的介绍
-
①. 哈希值是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
-
②. Object类中有一个方法可以获取对象的哈希值
public int hashCode():返回对象的哈希码值 -
③. 特点:
- 同一个对象多次调用hashCode() 方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不相同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
- ④. 哈希值原理
- ⑤. 自定义对象的唯一性
- 要求添加进Set中的元素所在的类,一定要重写equal()和 hashCode()方法,进而保存不可重复性
- hashCode():属性相同的对象返回值必须相同,属性不同的返回值尽量不同(提高效率)
- equals():属性相同返回true,属性不同返回false,返回false的时候就存储
[ 掌握关于equals方法和hashCode方法底层实现原理 ]
/*
public static int hashCode(Object a[])
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
为什么是31?
1.31是质数,质数是能被1和它本身整除的数
2.31这个数既不大也不小
3.31这个数好算,2的5次方-1,向左移动5位数-1
* */
@Override
public boolean equals(Object o)
if (this == o) return true;//调用的对象和传入的对象是同一个对象,直接返回true
if (o == null || getClass() != o.getClass()) return false;//传入的对象为空或者字节码文件不相同,返回false
Person person = (Person) o;//向下转型
return age == person.age &&
Objects.equals(name, person.name);
//如果调用对象的年龄和传入对象的年龄 相同并且 调用对象的姓名和传入对象的姓名相同返回true
- ⑥. HashSet的原理:当HashSet调用add()方法储存对象的时候,先调用对象的hashCode方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象。如果没有哈希值相同的对象就直接存入集合;如果有哈希值相同的对象,就和哈希值相同对象逐个进行equals()比较,比较结果为false就存入,true则不存
③. LinkedHashSet存取有序
-
①. 哈希表和链表实现的Set接口,具有可预测的迭代次序
-
②. 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
-
③. 由哈希表保证元素唯一,也就是说没有重复的元素
@Test
public void testLinkHashSet()
Set set=new LinkedHashSet();
set.add(123);
set.add(456);
set.add("AAA");
set.add("BBB");
set.add(null);
Iterator iterator=set.iterator();
while(iterator.hasNext())
System.out.println(iterator.next());//123 456 AAA BBB null
- ④.去除list中重复的元素
//将集合中重复的元素去掉
@Test
public void fun7()
ArrayList<String>list=new ArrayList<>();
list.add("AAA");
list.add("AAA");
list.add("AAA");
list.add("AAA");
list.add("AAA");
list.add("AAA");
list.add("BBB");
list.add("BBB");
list.add("CCC");
list.add("CCC");
getSingle(list);
// 打印
System.out.println(list);
public static void getSingle(ArrayList<String> list)
/*LinkedHashSet<String>lhs=new LinkedHashSet<>();
Iterator<String> iterator = list.iterator();
while(iterator.hasNext())
lhs.add(iterator.next());
for(String lhs2:lhs)
System.out.print(lhs2+"\\t");
*/
//1.创建一个LinkedHashSet集合
LinkedHashSet<String>lhs=new LinkedHashSet<>();
//2.将List集合中所有的元素添加到LinkedHashSet集合
lhs.addAll(list);
//3.将List 集合中元素清除
list.clear();
//4.将LinkedHashSet集合中的元素添加到List集合中
list.addAll(lhs);
④. TreeSet - 排序
- ①. .TreeSet的特点:元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet():根据其元素的自然排序进行排序
- TreeSet(Comparator comparator):根据指定的比较器进行排序
-
②. 没有带索引的方法,所以不能使用普通for循环遍历
-
③. 由于是Set集合,所以不包含重复元素的集合
-
④. 向TreeSet添加属性,需要添加同一类型的属性
⑤. 自然顺序(Comparable)
-
①. TreeSet类的add()方法中会把存入的对象提升为Comparable类型
-
②. 调用对象的CompableTo()方法和集合中的对象比较
-
③. 根据CompableTo()方法返回的结果进行储存
-
④. TreeSet底层是一个二叉树,两个叉。小的存储在左边(负数),大的存储在右边(正数),相等就不存0。CompareTo方法,在TreeSet集合如何存储元素取决于compareTo方法的返回值
- 返回的0,集合中只有一个元素
- 返回-1,集合会将存储的元素倒序
- 返回1,集合会怎么存就怎么取
public class TreeSetDemo
public static void main(String[] args)
TreeSet<Person> ts=Sets.newTreeSet();
ts.add(new Person("张三",23));
ts.add(new Person("李四",13));
ts.add(new Person("唐志",13));
ts.add(new Person("王五",43));
ts.add(new Person("赵六",33));
//[Person(name=李四, age=13), Person(name=张三, age=23), Person(name=赵六, age=33), Person(name=王五, age=43)]
System.out.println(ts);
@Data
@AllArgsConstructor
class Person implements Comparable
private String name;
private Integer age;
//按照年龄从小到大排序
public int compareTo(Object o)
Person p=(Person)o;
int num=this.age-p.age;//年龄是比较的主要条件
//int num=-this.age-p.age;//年龄从大到小排序
return num==0?this.name.compareTo(p.name):num;//姓名是比较的次要条件
- ⑤. 按照姓名长度进行排序
public class TreeSetDemo
public static void main(String[] args)
TreeSet<Person> ts=Sets.newTreeSet();
ts.add(new Person("张三",23));
ts.add(new Person("李四",13));
ts.add(new Person("李四",12));
ts.add(new Person("王五",43));
ts.add(new Person("赵六",33));
System.out.println('张'+0);//24352
System.out.println('李'+0);//26446
System.out.println('王'+0);//29579
System.out.println('赵'+0);//36213
//[Person(name=张三, age=23), Person(name=李四, age=12), Person(name=李四, age=13), Person(name=王五, age=43), Person(name=赵六, age=33)]
System.out.println(ts);
@Data
@AllArgsConstructor
class Person implements Comparable
private String name;
private Integer age;
//按照姓名进行排序,相同按照年龄进行排序
public int compareTo(Object o)
Person p=(Person)o;
int num=this.name.compareTo(p.name);
return num==0?this.age-p.age:num;
⑥. 比较器顺序(Comparator)
-
①. 创建TreeSet的时候可以制定一个Comparator接口
-
②. 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
-
③. 调用的对象是Comparator接口中compare()方法顺序
-
④. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
@Test
public void fun4()
/*
需求:将字符串按照长度排序
* */
//Comparator c=new CompareByLen();
//new TreeSet(Comparator );
TreeSet<String>ts=new TreeSet<>(new CompareByLen());
ts.add("aaaaaaaa");
ts.add("z");
ts.add("wc");
ts.add("nba");
ts.add("cba");
System.out.println(ts);//[n, bb, aaa]
class CompareByLen /* extends Object*/implements Comparator<String>//
@Override
public int compare(String s1, String s2)
//按照字符串长度进行比较
int num=s1.length()-s2.length();//长度为主要条件
return num==0?s1.compareTo(s2):num;//内容为次要条件
⑦. 两种排序比较
- ①. 自然顺序(Comparable)
- TreeSet 类的add()方法中会把存入的对象提升为Comparable类型
- 调用对象的CompableTo()方法和集合中的对象比较
- 根据CompableTo()方法返回的结果进行储存
- ②. 比较器顺序(Comparator)
- 创建TreeSet的时候可以制定一个Comparator接口
- 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
- 调用的对象是Comparator接口中compare()方法顺序
- 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
- ③. 两种方式的区别
- TreeSet如果传入Comparator,就优先按照Comparator
- TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCastE xception)
//java.lang.ClassCastException: com.itheima.TreeSetDemo4.Person cannot be cast to java.base/java.lang.Comparable
public class Person
private String name;
private int age;
public Person()
public Person(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 String toString()
return "Person" +
"name='" + name + '\\'' +
", age=" + age +
'';
@Test
public void fun1()
//1.按照年龄来排序
TreeSet<Person>ts=new TreeSet<>();
ts.add(new Person("张三",23));
ts.add(new Person("张三",23));
ts.add(new Person("张三",23));
ts.add(new Person("李四",24));
ts.add(new Person("王五",24));
System.out.println("ts = " + ts);
以上是关于JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序的主要内容,如果未能解决你的问题,请参考以下文章