接口、Map、可变参数"/>
Set接口、Map、可变参数
Set接口、Map、可变参数
第一章 Set接口(接昨天没学完的)
1.1HashSet集合存储数据的结构(哈希表)
哈希表
什么是哈希表呢?
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用数组处理冲突,同一hash值的链表都存储在一个数组里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
- 哈希表的初始化容量,数组长度为16个。
- 当数组容量不够时,扩容为原数组长度的2倍
- 加载因子为0.75。
- 指示当数组的容量被使用到长度的75%时,进行扩容。
如下图
1.2 HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一.
创建自定义Student类:
public class Student {private String name;private int age;//get/set@Overridepublic boolean equals(Object o) {if (this == o)return true;if (o == null || getClass() != o.getClass())return false;Student student = (Student) o;return age == student.age &&Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
创建测试类:
public class HashSetDemo2 {public static void main(String[] args) {//创建集合对象 该集合中存储 Student类型对象HashSet<Student> stuSet = new HashSet<Student>();//存储 Student stu = new Student("于谦", 43);stuSet.add(stu);stuSet.add(new Student("郭德纲", 44));stuSet.add(new Student("于谦", 43));stuSet.add(new Student("郭麒麟", 23));stuSet.add(stu);for (Student stu2 : stuSet) {System.out.println(stu2);}}
}
执行结果:
Student [name=郭德纲, age=44]
Student [name=于谦, age=43]
Student [name=郭麒麟, age=23]
1.3LinkedHashSet
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类java.util.LinkedHashSet
,底层数据结构是链表和哈希表的组合,其中链表保证元素有序 哈希表保证元素唯一:即先比较hashCode值 不同 添加到集合 相同 继续比较equals 不同 添加进集合 相同 不添加。
此实现与 HashSet的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
public class Demo01_LinkedHashSet {public static void main(String[] args) {Set<Person> set = new LinkedHashSet<>();set.add(new Person("柳岩",38));set.add(new Person("唐嫣",18));set.add(new Person("柳岩",38));// System.out.println(set);Iterator<Person> it = set.iterator();while (it.hasNext()){Person p = it.next();System.out.println(p.getName() + " "+p.getAge());}for(Person p : set){System.out.println(p.getName() + " "+p.getAge());}}
}
第二章 Map集合 映射
2.1 概述
现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map
接口。
我们通过查看Map
接口描述,发现Map
接口下的集合与Collection
接口下的集合,它们存储数据的形式不同,如下图。
Collection
中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。Map
中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。Collection
中的集合称为单列集合,Map
中的集合称为双列集合。- 需要注意的是,
Map
中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
2.2 Map接口中的常用方法
public V put(K key, V value)
: 把指定的键与指定的值添加到Map集合中。public V remove(Object key)
: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。public V get(Object key)
根据指定的键,在Map集合中获取对应的值。public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。public boolean containKey(Object key)
:判断该集合中是否有此键。public Collection<V> values()
返回Map集合中的所有值到Collection集合。
public class Demo01_Map {public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();
// map = new HashMap<>();
// map = new LinkedHashMap<>();map.put("柳岩",38);map.put("唐嫣",18);map.put("金莲",138);map.put("大郎", 8);//如果键相同 值会覆盖 会返回被覆盖的值
// Integer in = map.put("大郎", 108);
// System.out.println(in);System.out.println(map);// //根据键找值
// Integer integer = map.get("柳岩");
// System.out.println(integer);
//
// //判断集合是否包含指定键
// boolean b = map.containsKey("柳岩");
// System.out.println(b);//根据键删除一对元素 返回被删除的值Integer removeValue = map.remove("柳岩");System.out.println(removeValue);System.out.println(map);}
}public class Demo02_Map {public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();map.put("柳岩",38);map.put("唐嫣",18);map.put("金莲",138);map.put("大郎", 8);//添加元素 键相同 值不覆盖 返回原来的值
// Integer value = map.putIfAbsent("大郎", 108);
// System.out.println(value);
// System.out.println(map);//根据键找值 如果有指定键 返回对应的值 如果没有给定键 则返回给定的默认值
// Integer value2 = map.getOrDefault("柳岩2", 100);
// System.out.println(value2);//根据键和值删除 一对元素 键和值都相同 才能删除boolean b = map.remove("柳岩", 38);System.out.println(b);System.out.println(map);//1.8 默认方法
// map.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String key, Integer value) {
// System.out.println(key+" "+value);
// }
// });// map.forEach((k,v)-> System.out.println(k+" "+v));}
}
注意:使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中; 若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。
2.3 Map集合遍历
方式1:键找值方式
通过元素中的键,获取键所对应的值
分析步骤:
1.定义Map集合 添加数据
2.调用keySet方法 获取存储所有键的Set集合
3.遍历Set集合 依次获取到每个元素(Map集合的key)
4.调用Map集合的get方法 根据键找到对应的值
遍历图解:
代码演示
public class Demo03_Map {public static void main(String[] args) {Map<String,Integer> map = new HashMap<>();map.put("柳岩",38);map.put("唐嫣",18);map.put("金莲",138);map.put("大郎", 8);// 2.调用keySet方法 获取存储所有键的Set集合Set<String> set = map.keySet();//迭代器Iterator<String> it = set.iterator();while(it.hasNext()){// 3.遍历Set集合 依次获取到每个元素(Map集合的key)String key = it.next();//4.调用Map集合的get方法 根据键找到对应的值Integer value = map.get(key);System.out.println(key+" = "+value);}//增强forfor(String key : set){System.out.println(key+" = "+map.get(key));}}
}
方式2:键值对方式
即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
Entry键值对对象:
我们已经知道,Map
中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map
中是一一对应关系,这一对对象又称做Map
中的一个Entry(项)
。Entry
将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map
集合时,就可以从每一个键值对(Entry
)对象中获取对应的键与对应的值。
在Map集合中也提供了获取所有Entry对象的方法:
public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。
获取了Entry对象 , 表示获取了一对键和值,那么同样Entry中 , 分别提供了获取键和获取值的方法:
public K getKey()
:获取Entry对象中的键。public V getValue()
:获取Entry对象中的值。
操作步骤与图解:
- 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示:
entrySet()
。 - 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
- 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示:
getkey() getValue()
遍历图解:
public class Demo04_Map {public static void main(String[] args) {Map<String,Integer> map = new HashMap<>();map.put("柳岩",38);map.put("唐嫣",18);map.put("金莲",138);map.put("大郎", 8);//2.调用entrySet 获取到存储结婚证(键值对映射关系对象)的Set集合Set<Map.Entry<String,Integer>> set = map.entrySet();//迭代器Iterator<Map.Entry<String,Integer>> it = set.iterator();while(it.hasNext()){//3.遍历Set集合 依次获取到每个结婚证 对象Map.Entry<String,Integer> en = it.next();// 4.调用结婚证对象的方法 获取到 键 和值String key = en.getKey();Integer value = en.getValue();System.out.println(key + " = "+value);}for(Map.Entry<String,Integer> en: set){System.out.println(en.getKey() + " = "+en.getValue());}}
}
2.4 HashMap集合
Map接口实现类HashMap类特点:
- 底层哈希表结构。
- 不允许重复键。
- 用作键的对象,应该重写hashCode()方法和equals()方法。
- 此集合可以使用null值和null键。
- 线程不安全,运行速度快。
2.5 HashMap存储自定义对象
//定义Person类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;}@Overridepublic String toString() {return name +" "+age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;if (age != person.age) return false;return name != null ? name.equals(person.name) : person.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
}
测试类:
public class Demo01_HashMap {public static void main(String[] args) {Map<Person,String> map = new HashMap<>();//允许null键和null值
// map.put(null,null);
// map.put(null,"aaa");map.put(new Person("柳岩",38),"bj");map.put(new Person("唐嫣",18),"sh");map.put(new Person("小苍",50),"rb");map.put(new Person("小苍",50),"sj");
// System.out.println(map);//keySetSet<Person> set = map.keySet();for(Person key : set){System.out.println(key.getName()+" "+key.getAge()+" = "+map.get(key));}//entrySetSet<Map.Entry<Person,String>> set2 = map.entrySet();for(Map.Entry<Person,String> en: set2){Person key = en.getKey();String value = en.getValue();System.out.println(key.getName()+" "+key.getAge()+" = "+map.get(key));}}
}
运行结果
柳岩 38 = bj
唐嫣 18 = sh
小苍 50 = sj
柳岩 38 = bj
唐嫣 18 = sh
小苍 50 = sj
- 当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法(如果忘记,请回顾HashSet存放自定义对象)。
- 如果要保证map中存放的key和取出的顺序一致,可以使用
java.util.LinkedHashMap
集合来存放。
2.6 LinkedHashMap介绍
我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?
在HashMap下面有一个子类LinkedHashMap,底层是哈希表双向链表,保证迭代的顺序。
public static void main(String[] args) {LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();map.put("邓超", "孙俪");map.put("李晨", "范冰冰");map.put("刘德华", "朱丽倩");Set<Entry<String, String>> entrySet = map.entrySet();for (Entry<String, String> entry : entrySet) {System.out.println(entry.getKey() + " " + entry.getValue());}
}
2.7 Properties集合
Map接口实现类Hashtable的子类Properties类。Properties也是Map接口实现类,是存储键值对的双列集合,由于此类能和IO流结合使用,数据可以持久化,使用量很大。(IO部分后面课程详解)
Properties集合特点:
- 继承Hashtable,底层数据结构是哈希表。
- 线程安全,运行速度慢。
- 不允许null值,null键。
- 此集合存储键值对数据类型固定为String。
- 可以和IO流结合使用,从流中加载数据。
Properties集合特有方法:
Object setPropery(String key,String value)
,向集合中存储键值对。String getProperty(String key)
,获取集合中键对应的值,无此键返回null。Set<String> stringPropertyNames()
,集合中的所有键存储到Set集合。void load(输入流对象)
,IO部分讲解。
public class Demo01_Properties {public static void main(String[] args) {Properties p = new Properties();p.setProperty("name","liuyan");p.setProperty("age","38");p.setProperty("email","123@qq");
// System.out.println(p);Set<String> set = p.stringPropertyNames();for(String key : set){String value = p.getProperty(key);System.out.println(key + " = "+value);}}
}
运行结果
age = 38
name = liuyan
email = 123@qq
2.8 TreeMap集合yun
TreeMap集合基于红黑树实现,该映射根据其键的[自然顺序]进行排序,或者根据创建映射时提供Comparator
进行排序,具体取决于使用的构造方法。
构造方法 | 描述 |
---|---|
TreeMap() | 使用键的自然顺序构造一个新的、空的树映射,必须实现自然排序接口。 |
TreeMap(Comparator<? super K> comparator) | 构造一个新的、空的树映射,该映射根据给定比较器进行排序。 |
TreeMap(Map<? extends K,? extends V> m) | 构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序。 |
//定义Person类
public class Person implements Comparable<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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Person o) {if(this.age == o.age){return this.namepareTo(o.name);}return this.age - o.age;}
}
public class Demo01_TreeMap {public static void main(String[] args) {Map<Person,String> map = new TreeMap<>(new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {if(o2.getAge() == o1.getAge()){return o2.getName()pareTo(o1.getName());}return o2.getAge() - o1.getAge();}});//不允许null键 允许null值// map.put(10,null);map.put(new Person("柳岩",38),"bj");map.put(new Person("唐嫣",18),"sh");map.put(new Person("小苍",50),"rb");map.put(new Person("小苍",50),"sj");System.out.println(map);System.out.println("----------------------------------------------");Map<Integer,String> hashMap = new LinkedHashMap<>();hashMap.put(1,"aaa");hashMap.put(3,"aaa");hashMap.put(2,"aaa");hashMap.put(4,"aaa");//System.out.println(hashMap);Map<Integer,String> treeMap = new TreeMap<>(hashMap);System.out.println(treeMap);}
}
运行结果
{Person{name='小苍', age=50}=sj, Person{name='柳岩', age=38}=bj, Person{name='唐嫣', age=18}=sh}
----------------------------------------------
{1=aaa, 2=aaa, 3=aaa, 4=aaa}
public Map.Entry<K,V> ceilingEntry(K key)
: 返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。public K ceilingKey(K key)
: 返回大于等于给定键的最小键;如果不存在这样的键,则返回 null。public Map.Entry<K,V> firstEntry()
返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。public Map.Entry<K,V> lastEntry()
: 返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。public K firstKey()
: 返回此映射中当前第一个(最低)键。public K lastKey()
:返回映射中当前最后一个(最高)键。
public class Demo02_TreeMap {public static void main(String[] args) {TreeMap<Integer,String> map = new TreeMap<>();map.put(10,"aa");map.put(30,"aa");map.put(20,"aa");map.put(40,"aa");//获取最小键Integer firstKey = map.firstKey();System.out.println(firstKey);//获取最小键的键值对Map.Entry<Integer, String> firstEntry = map.firstEntry();System.out.println(firstEntry);//获取最大键Integer lastKey = map.lastKey();System.out.println(lastKey);//获取最大键的键值对Map.Entry<Integer, String> lastEntry = map.lastEntry();System.out.println(lastEntry);System.out.println("---------------------------");//获取 >=指定键的 最小键Integer ceilingKey = map.ceilingKey(15);System.out.println(ceilingKey);Map.Entry<Integer, String> ceilingEntry = map.ceilingEntry(11);System.out.println(ceilingEntry);//获取 <=指定键的 最小键Integer floorKey = map.floorKey(15);System.out.println(floorKey);Map.Entry<Integer, String> floorEntry = map.floorEntry(25);System.out.println(floorEntry);}
}
2.8 Map集合练习
需求:
计算一个字符串中每个字符出现次数。
分析:
- 获取一个字符串对象
- 创建一个Map集合,键代表字符,值代表次数。
- 遍历字符串得到每个字符。
- 判断Map中是否有该键。
- 如果没有,第一次出现,存储次数为1;如果有,则说明已经出现过,获取到对应的值进行++,再次存储。
- 打印最终结果
方法介绍
public boolean containKey(Object key)
:判断该集合中是否有此键。
public class Test_Map {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入一个字符串:");String line = sc.nextLine();Map<Character,Integer> map = new TreeMap<>();char[] chs = line.toCharArray();for (char ch : chs) {//判断是否有当前字符 作为键if(map.containsKey(ch)){//有 说明不是第一次添加//需要先获取到值Integer count = map.get(ch);//将值+1 在添加到map集合中map.put(ch,count+1);}else{//没有 说明第一次添加map.put(ch,1);}}System.out.println(map);}
}
运行结果
asdfsadasdasd
{a=4, d=4, f=1, s=4}
第三章 可变参数
3.1 可变参数
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化.
格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
注意事项
1.一个方法只能有一个可变参数
2.如果方法有多个参数 可变参数放到最后
3.最牛的可变参数 Object...obj 任意类型 任意个数
代码演示:
public class Demo01_VarArgs {public static void main(String[] args) {int sum = sum(10, 20);System.out.println(sum);int sum2 = sum(10, 20, 30);System.out.println(sum2);int[] arr = {10,20,30,40};int sum3 = sum(arr);System.out.println(sum3);System.out.println("-----------------------------");ArrayList<String> list = new ArrayList<>();list.add("aa");list.add("bb");list.add("cc");System.out.println(list);/*Collections 集合工具类public static <T> boolean addAll(Collection<T> c, T... elements):*/Collections.addAll(list,"abc","bcd","aaa","bbb");System.out.println(list);}public static int sum (int...a ){int sum = 0;for (int i : a) {sum += i;}return sum;}
}
运行结果
30
60
100
-----------------------------
[aa, bb, cc]
[aa, bb, cc, abc, bcd, aaa, bbb]Process finished with exit code 0
注意:
- 可变参数的本质是数组。
- 不传递参数,数组的长度是0.
- 传递几个参数,数组的长度就是几。
- 一个方法中只能有一个可变参数。
- 如果方法中有多个参数,可变参数只能写在最后一位。
3.2 可变参数应用
在Collections中也提供了添加一些元素方法:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。
public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<Integer>();//原来写法//list.add(12);//list.add(14);//list.add(15);//list.add(1000);//采用工具类 完成 往集合中添加元素 Collections.addAll(list, 5, 222, 1,2);System.out.println(list);
}
第四章 斗地主案例排序
4.1 案例介绍
按照斗地主的规则,完成洗牌发牌的动作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n1wEbKMI-1681214015627)(img/斗地主.png)]
具体规则:
- 组装54张扑克牌将。
- 54张牌顺序打乱。
- 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
- 查看三人各自手中的牌(按照牌的大小排序)、底牌。
规则:手中扑克牌从大到小的摆放顺序:大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3。
4.2 案例需求分析
- 准备牌:
完成数字与纸牌的映射关系:
使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系(相当于一个字典)。
- 洗牌:
通过数字完成洗牌发牌
- 发牌:
将每个人以及底牌设计为ArrayList,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。
存放的过程中要求数字大小与斗地主规则的大小对应。
将代表不同纸牌的数字分配给不同的玩家与底牌。
- 看牌:
通过Map集合找到对应字符展示。
通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wiNMlMzI-1681214015627)(img/斗地主分析.png)]
4.3 代码实现
public class PooKer {public static void main(String[] args) {//定义一个Map集合用来存储 牌索引 扑克牌Map<Integer,String>map = new HashMap<>();//定义一个list集合 存储牌索引List<Integer> suoYin = new ArrayList<>();//定义花色数组String[] colors = {"♥","♠","♣","♦"};//定义牌的数组String[] nums = "2-3-4-5-6-7-8-9-10-J-Q-K-A".split("-");int index= 2;//定义牌的索引for (String num : nums) {for (String color : colors) {String thispooKer = color + num;map.put(index,thispooKer);index ++ ;}}//单独添加大小王map.put(0,"大🐕");map.put(1,"小🐕");//为list集合添加索引for (int i = 0 ; i < 54 ; i ++){suoYin.add(i);}//创建玩家集合和底牌集合List<Integer> play1 = new ArrayList<>();List<Integer> play2 = new ArrayList<>();List<Integer> play3 = new ArrayList<>();List<Integer> dipai = new ArrayList<>();//洗牌Collections.shuffle(suoYin);for (int i = 0; i < suoYin.size(); i++) {Integer fapai = suoYin.get(i);if (i>=51){dipai.add(fapai);} else if (i % 3 == 0) {play1.add(fapai);}else if(i % 3 == 1){play2.add(fapai);} else{play3.add(fapai);}}//进行排序Collections.sort(play1);Collections.sort(play2);Collections.sort(play3);Collections.sort(dipai);//看牌show("周星驰",play1,map);show("周润发",play2,map);show("刘德华",play3,map);show("底牌",dipai,map);}public static void show (String name,List<Integer>play,Map<Integer,String> map){//定义一个StringBuilder类,遍历集合 索引出Map集合中对应的值 并拼接成一个[String,String,String]的字符串组合StringBuilder sb = new StringBuilder();//先添加一个[sb.append("[");for (int i = 0; i < play.size(); i++) {//倒出key值Integer key = play.get(i);//倒出Map集合中对应Key的键值String pooKer2 = map.get(key);//添加如字符串数组中sb.append(pooKer2);if (i == play.size()-1){sb.append("]");}else {sb.append(", ");}}System.out.println(name+" : "+sb.toString());}
}
第五章 集合总结
Collection 单列集合顶层接口 List 有序 有索引 元素可重复 ArrayList 扩容1.5倍底层数据结构是数组 查询快增删慢 线程不安全 效率高LinkedList底层数据结构是链表 查询慢 增删快线程不安全 效率高Vector JDK1.0 扩容2倍底层数据结构是数组 查询快增删慢 线程安全 效率低Set 元素唯一TreeSet底层数据结构是红黑树 排序 唯一 不允许null值排序:1.空参构造 要求集合中的元素必须实现自然排序接口Comparable 重写compareTo方法2.带参构造 需要传入比较器对象 Comparator 重写compare方法 唯一:1.自然排序接口 需要看 compareTo方法返回值是否为0 0代表相同2.比较器接口 需要看 compare方法 返回值是否为0 0代表相同HashSet底层数据结构是哈希表 无序 唯一 允许null元素先比较hashCode 不同 添加到集合 相同 继续比较equals 不同 添加到集合相同 不添加 注意:HashSet存储自定义类型 要想保证元素唯一 必须重写hashCode和equals方法 LinkedHashSet底层数据结构是链表+哈希表 链表保证有序 哈希表保证唯一 有序 唯一 允许null元素先比较hashCode 不同 添加到集合 相同 继续比较equals 不同 添加到集合相同 不添加 Map 双列集合的顶层接口 HashMap底层数据结构是哈希表 键 无序 唯一 允许null键 null值 先比较hashCode 不同 添加到集合 相同 继续比较equals 不同 添加到集合相同 值覆盖LinkedHashMapTreeMap底层数据结构是红黑树 键 排序 唯一 不允许null键 允许null值 排序:1.空参构造 要求集合中的元素必须实现自然排序接口Comparable 重写compareTo方法2.带参构造 需要传入比较器对象 Comparator 重写compare方法 唯一:1.自然排序接口 需要看 compareTo方法返回值是否为0 0代表相同2.比较器接口 需要看 compare方法 返回值是否为0 0代表相同Hashtable JDK1.0 线程安全的 效率低 底层哈希表 不允许null键null值
更多推荐
Set接口、Map、可变参数
发布评论