集合
Java 集合框架
Java Collection Framework
,又被称为容器container
,是定义在java.util
包下的一组接口interfaces
和其实现类classes
Set和Map集合的关系
Set
-
纯key模型
应用: 查询某个英文单词在不在字典中
Map
-
key-value模型
应用:统计每个单词出现的次数<单词,出现次数>
Map集合
Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
Map中存放键值对的Key是唯一的,value是可以重复的.HashMap集合中key和value都可以为null,但是key为null,只能有一个.
Map中的Key可以全部分离出来,存储到Set中来进行访问。
Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复)。
Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行重新插入
TreeMap
TreeMap集合中key
不能为null,value
可以为null
HashMap
map中如何比较两个对象
必须覆写hashcode()
和equals
方法.
equal相同的两个对象,hashcode是否相同?
一定相同,equal相同,就是同一对象, 试想,如果hashcode()不相同,那肯定不是同一对象,怎么可能equals()相同
hashcode()相同的两个对象,equals是否相同?
不一定相同,只能说明发生了哈希冲突.
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Person) {
Person person = (Person) obj;
return this.age == person.age && this.name.equals(person.name);
}
return false;
}
@Override
public int hashCode() {
return 0;
}
public static void main(String[] args) {
Person per1 = new Person("张三", 20);
Person per2 = new Person("李四", 30);
Person per3 = new Person("张三", 20);
Map<Person, Object> map = new HashMap<>();
map.put(per1, 1);
map.put(per2, 2);
map.put(per3, 3);
//只要equals()方法比较相同,JDK就会认为他们是相同的对象
System.out.println(map);
//打印结果:{Person{name='张三', age=20}=3, Person{name='李四', age=30}=2}
//如果不重写equals(),那么即使他们的hashcode相同,JDK也认为他们是不同的对象
// 不重写equals() 打印结果为
//{Person{name='张三', age=20}=1, Person{name='李四', age=30}=2, Person{name='张三', age=20}=3}
}
}
TreeMap如何保证key的顺序
/**
* TreeMap 和 HashMap 的比较
* TreeMap中元素的保存顺序是由compareTo()方法决定的
* 如果要使用TreeMap集合保存元素,要么实现Comparable,要么传入一个比较器,
* 要不然会报错误 //jcl.Student cannot be cast to java.lang.Comparable
*/
public static void main(String[] args) {
Set<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
});
Student s1 = new Student("diaochan");
Student s2 = new Student("wangzhoajun");
Student s3 = new Student("yangyuhuan");
Student s4 = new Student("xishi");
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
for (Student s : set) {
System.out.println(s.getName() + "");
}
}
}
/**
打印结果:
diaochan
wangzhoajun
xishi
yangyuhuan
**/
Map的常用方法
put(key, value)
:插入一个键值对,如果 key 已经存在,则会替换原有的 value 值。
get(key)
:返回指定 key 对应的 value 值,如果 key 不存在,则返回 null。
containsKey(key)
:判断 Map 中是否包含指定的 key,如果包含则返回 true,否则返回 false。
containsValue(value)
:判断 Map 中是否包含指定的 value,如果包含则返回 true,否则返回 false。
keySet()
:返回 Map 中所有键的集合,即一个 Set 集合。
values()
:返回 Map 中所有值的集合,即一个 Collection 集合。
entrySet()
:返回 Map 中所有键值对的集合,即一个 Set 集合,其中每个元素都是一个 Entry 对象,包含一个键和对应的值。
remove(key)
:移除 Map 中指定 key 对应的键值对,如果 key 不存在,则不进行任何操作。
size()
:返回 Map 中键值对的数量。
isEmpty()
:判断 Map 是否为空,如果为空则返回 true,否则返回 false。
Map接口常见子类添加问题
Map<String, String> map = new HashMap<>();
//V put(K key, V value)
//将指定的值与该映射中的指定键相关联
//key值不重复,value值可以重复
map.put("豹子头", "林冲");
map.put("智多星", "吴用");
map.put("及时雨", "宋江");
map.put("黑旋风", "李逵");
//在Map中元素添加的顺序和保存的顺序没有必然联系
System.out.println(map);
//Set<Map.Entry<K,V>> entrySet()
//返回此地址中包含的映射的Set视图。
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
//V get(Object key)
//返回指定键所映射的值,如果不存在,返回null
System.out.println(map.get("智多星"));
System.out.println(map.get("智多"));//null
//V put(K key, V value)
//将指定的值与该映射中的指定键相关联,若key不存在,则新增加一个Entry对象
//若key存在,则将原来的value改为新的value,并返回原来的value.
map.put("花和尚", "鲁智深");
System.out.println(map);
System.out.println(map.put("花和尚", "小明"));
System.out.println(map);
//Set<K> keySet()
//返回此地图中包含的键的Set集合
System.out.println("当前的所有key为:");
System.out.println(map.keySet());
//Collection<V> values()
//返回此地图中包含的值的Collection集合
System.out.println("当前的所有value为:");
System.out.println(map.values());
map集合的遍历
Map<String, String> map = new HashMap<>();
map.put("豹子头", "林冲");
map.put("智多星", "吴用");
map.put("及时雨", "宋江");
map.put("黑旋风", "李逵");
//Set<Map.Entry<K,V>> entrySet()
//返回此地址中包含的映射的Set视图。
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
// Set<K> keySet() 返回此地图中包含的键的Set集合
System.out.println("当前的所有key为:");
Set<String> strings = map.keySet();
for (String ret : strings) {
System.out.println(ret);
}
//Collection<V> values() 返回此地图中包含的值的Collection集合
System.out.println("当前的所有value为:");
Collection<String> values = map.values();
for (String ret : values) {
System.out.println(ret);
}
/**
打印结果:
map集合的key-value
智多星=吴用
黑旋风=李逵
豹子头=林冲
及时雨=宋江
当前的所有key为:
智多星
黑旋风
豹子头
及时雨
当前的所有value为:
吴用
李逵
林冲
宋江
**/
Set集合
Set是继承自Collection的一个接口类 Set中只存储了key,并且要求key一定要唯一 Set的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的 Set最大的功能就是对集合中的元素进行去重 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础上维护了一个双向链表来记录元素的插入次序。 Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入 Set中不能插入null的key。