一阶段:第11天:Set和Map(8.6)
一.Set
1.1Set接口的使用
特点:(1)无序:添加顺序跟打印顺序不一样(2)不能排重
常用实现类: HashSet、LinkedHashSet、TreeSet(还实现了SortedSet接口)
常用方法:
方法名 | 描述 |
---|---|
add(E e) | 确保此 collection 包含指定的元素(可选操作)。 |
addAll(Collection<? extends E> c) | 将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。 |
clear() | 移除此 collection 中的所有元素(可选操作)。 |
contains(Object o) | 如果此 collection 包含指定的元素,则返回true。 |
containsAll(Collection<?> c) | 如果此 collection 包含指定 collection 中的所有元素,则返回 true。 |
equals(Object o) | 比较此 collection 与指定对象是否相等。 |
isEmpty() | 如果此 collection 不包含元素,则返回true。 |
iterator() | 返回在此 collection 的元素上进行迭代的迭代器。 |
remove(Object o) | 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 |
removeAll(Collection<?> c) | 移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。 |
retainAll(Collection<?> c) | 仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 |
size() | 返回此 collection 中的元素数。 |
toArray() | 返回包含此 collection 中所有元素的数组。 |
public class SetDemo {
public static void main(String[] args) {
//创建集合
Set<String> names=new HashSet<>();
//添加元素
names.add("少泊");
names.add("zz");
names.add("真真");
names.add("真真");
System.out.println(names.toString());
//删除
/*names.remove("zz");
System.out.println("删除之后:"+names.toString());*/
//遍历
//增强for
for (String name : names) {
System.out.println(name);
}
//迭代器
System.out.println("-------迭代器------");
Iterator<String> it=names.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
//判断是否存在
System.out.println(names.contains("zz"));
}
}
1.2 HashSet
- HashSet特点:(1)无序(2)不能重复(3)此类允许使用null元素。
- 需要重写equals()和hashCode()方法
- 存储结构:哈希表=数组+链表(jdk1.7之前,jdk1.8及之后数组+链表+红黑树)
- 红黑树形成条件:总容量大于64,链表长度大于等于8
- 红黑树(类似二叉树)查找效率高,当层级相差较大时,会自动进行优化
- HashSet集合能实现排重(重写了equals和hashCode方法之后的HashSet)
public class HashSetDemo {
public static void main(String[] args) {
//创建集合
HashSet<String> hashSet=new HashSet<>();//初始容量16
//l添加元素
hashSet.add("北京");
hashSet.add("上海");
hashSet.add("上海");
hashSet.add("杭州");
System.out.println(hashSet.toString());
//删除
hashSet.remove("上海");
System.out.println("删除之后:"+hashSet.toString());
//遍历
//增强for
System.out.println("-------for-----");
for (String s : hashSet) {
System.out.println(s);
}
//迭代器
System.out.println("----迭代器-----");
Iterator<String> it=hashSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(hashSet.contains("北京"));
}
}
成员是对象的:
public class HashSetDemo2 {
public static void main(String[] args) {
//创建集合
HashSet<Student> students=new HashSet<>();
Student s1=new Student("z1",11);
Student s2=new Student("z2",12);
Student s3=new Student("z3",13);
Student s4=new Student("z4",14);
Student s5=new Student("z5",15);
Student s6=new Student("z5",15);
//添加元素
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(s5);
students.add(s6);
System.out.println("元素个数:"+students.size());
System.out.println(students.toString());
//删除
students.remove(s6);
System.out.println("删除之后:"+students.size());
//遍历
//增强for
System.out.println("-----增强for-----");
for (Student student : students) {
System.out.println(student);
}
//迭代器
System.out.println("----迭代器----");
Iterator<Student> it=students.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
1.3 LinkedHashSet
存储特点:有序存储,排重,通过链表实现的集合的有序。
LinkedHashSet集合的元素排重与HashSet集合排重方法一致。
public class LinkedHashSetDemo {
public static void main(String[] args) {
//创建集合
LinkedHashSet<String> linkedHashSet=new LinkedHashSet<>();
//添加
linkedHashSet.add("安卓");
linkedHashSet.add("za");
linkedHashSet.add("ff");
System.out.println(linkedHashSet.toString());
}
}
1.4 TreeSet集合
- TreeSet特点:(1)无序(2)不能重复(3)排序
- 存储结构:自平衡红黑二叉树
- 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator进行排序,具体取决于使用的构造方法。
public class TreeSetDemo {
public static void main(String[] args) {
//创建一个集合
TreeSet<String> treeSet=new TreeSet<>();
//添加元素
treeSet.add("hello");
treeSet.add("worl");
treeSet.add("java");
treeSet.add("php");
treeSet.add("html");
treeSet.add("ui");
System.out.println(treeSet.toString());
//删除
treeSet.remove("html");
System.out.println("删除之后:"+treeSet.toString());
//遍历
//增强for
System.out.println("----增强for-----");
for (String s : treeSet) {
System.out.println(s);
}
//迭代器
System.out.println("--------正常迭代器-----");
Iterator<String> it=treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
System.out.println("-----降序迭代器----");
Iterator<String> dit=treeSet.descendingIterator();
while (dit.hasNext()){
System.out.println(dit.next());
}
//判断
System.out.println(treeSet.contains("java"));
}
}
比较器:
- 要求:集合元素必须继承Comparable接口或者自创一个接口
- 创建集合继承接口并指定比较器—会使用比较器,比较器的优先级高
public class TreeSetDemo2 {
public static void main(String[] args) {
//创建集合
TreeSet<Student> treeSet=new TreeSet<>();
//创建集合并指定比较器---比较器的优先级高
//TreeSet<Student> treeSet=new TreeSet<>(new MyComparator());
//添加元素
Student s1=new Student("z1",11);
Student s2=new Student("z2",12);
Student s3=new Student("z3",13);
Student s4=new Student("z4",14);
Student s5=new Student("z5",15);
Student s6=new Student("z5",15);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
System.out.println(treeSet.toString());
//删除
treeSet.remove(new Student("z1",11));
//遍历
//增强for
System.out.println("----增强for----");
for (Student student : treeSet) {
System.out.println(student);
}
System.out.println("----迭代器----");
Iterator it=treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(treeSet.contains(new Student("z2",12)));
//SortedSet中方法
System.out.println(treeSet.first());
System.out.println(treeSet.last());
}
}
自创比较器:
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
}
在集合里创建比较器,实现Comparable接口
public class Student implements Comparable<Student>{
......
@Override
public int compareTo(Student o) {
int n1=this.name.compareTo(o.name);
int n2=this.age-o.age;
System.out.println("this:"+this.name);
System.out.println("o:"+o.name);
return n1==0?n2:n1;
}
}
二.Map接口
Map接口是将键映射到值的对象。一个映射不能包含重复的键,每个键最多只能映射到一个值,值可以重复。
map集合中若向集合中添加相同键的键值对时,新的值会将旧的值覆盖。无序。
Map常用实现类:HashMap、LinkedHashMap、Hashtable、TreeMap
Map接口的常用方法:
方法名 | 描述 |
---|---|
clear() | 从此映射中移除所有映射关系(可选操作)。 |
containsKey(Object key) | 如果此映射包含指定键的映射关系,则返回 true。 |
containsValue(Object value) | 如果此映射将一个或多个键映射到指定值,则返回 true。 |
entrySet() | 返回此映射中包含的映射关系的 Set集合。 |
equals(Object o) | 比较指定的对象与此映射是否相等。 |
get(Object key) | 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。 |
hashCode() | 返回此映射的哈希码值。 |
isEmpty() | 如果此映射未包含键-值映射关系,则返回 true。 |
keySet() | 返回此映射中包含的键的 Set 集合。 |
put(K key, V value) | 将指定的值与此映射中的指定键关联(可选操作)。 |
putAll(Map<? extends K,? extends V> m) | 从指定映射中将所有映射关系复制到此映射中(可选操作)。 |
remove(Object key) | 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。 |
size() | 返回此映射中的键-值映射关系数。 |
public class MapDemo {
public static void main(String[] args) {
//创建集合
Map<String,String> map=new HashMap<>();
//添加元素
map.put("cn", "中国");
map.put("cn", "中华人民共和国");//中国被替换掉了//中国作为返回值了
map.put("usa", "美国");
map.put("uk", "英国");//返回值为null
/*System.out.println(map.put("cn", "中国"));
System.out.println(map.put("cn", "中华人民共和国"));//中国被替换掉了//中国作为返回值了
System.out.println(map.put("usa", "美国"));
System.out.println(map.put("uk", "英国"));//返回值为null*/
System.out.println(map.toString());
//删除
map.remove("uk");
System.out.println("删除之后"+map.toString());
//遍历
//使用keySet遍历Set<String>
System.out.println("--------keyset------");
Set<String> keyset=map.keySet();
for (String s : keyset) {
System.out.println(s+"-----"+map.get(s));
}
//使用entrySet遍历Set<Map.Entry<String,String>>
System.out.println("-----entrySet-----");
Set<Map.Entry<String,String>>entries=map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"-----"+entry.getValue());
}
//判断
//判断key是否存在
System.out.println(map.containsKey("cn"));
//判断value是否存在
System.out.println(map.containsValue("中国"));
}
}
2.1HashMap
相对无序存储,通过哈希表实现的集合。
HashMap集合的排重,只需要重写键所属的类的hashCode和equals方法即可。
* 需求:使用Student作为key,地址作为value
public class HashMapDemo2 {
public static void main(String[] args) {
//创建HashMap
HashMap<Student,String> hashMap=new HashMap<>();
Student s1=new Student("少泊",20);
Student s2=new Student("法海",18);
Student s3=new Student("真真",19);
Student s4=new Student("真真",19);
hashMap.put(s1, "北京");
hashMap.put(s2, "南京");
hashMap.put(s3, "东京");
hashMap.put(s4, "西京");
System.out.println(hashMap.toString());
//删除
//hashMap.remove("法海",18);
hashMap.remove(s2,"南京");
System.out.println(hashMap);
//遍历
for (Student student : hashMap.keySet()) {
System.out.println(student+"----"+hashMap.get(student));
}
for (Map.Entry<Student, String> entry : hashMap.entrySet()) {
System.out.println(entry);
}
}
}
2.2 LinkedHashMap
LinkedHashMap集合是具有可预知迭代顺序的Set接口的哈希表和链接列表实现。此实现与HashSet的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。用法与HashSet类似。
存储特点:有序存储,元素排重,通过链表实现的集合。
2.3 Hashtable
此类实现一个哈希表,该哈希表将键映射到相应的值。任何非null对象都可以用作键或值。Hashtable有一个子类Properties,Properties集合使用的比较频繁。
存储特点:相对无序存储,元素排重,通过哈希表实现的集合。
HashMap与Hashtable的区别:
1)Hashtable线程安全的,而HashMap线程不安全的
2)Hashtable中不允许存在null的键和null值,但是HashMap中允许null的键和null值
2.4 TreeMap
存储结构:自平衡红黑二叉树
特点:存储键值对、键不能重复、一个键对应一个值、值可以重复。无序,数据会进行排序。
排重依据:Comparable接口的compareTo()方法的返回值。如果返回0就认为是重复的元素。
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Student,String> treeMap=new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Student s1=new Student("少泊",20);
Student s2=new Student("法海",18);
Student s3=new Student("真真",19);
treeMap.put(s1,"北京");
treeMap.put(s2,"南京");
treeMap.put(s3,"东莞");
System.out.println(treeMap.toString());
//删除
treeMap.remove(new Student("真真",19));
System.out.println(treeMap.toString());
//遍历
for (Student student : treeMap.keySet()) {
System.out.println(student.toString()+"----"+treeMap.get(student));
}
for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey()+"----"+entry.getValue());
}
}
}