Java集合最后一小节。
前两节:
【Java】(二十)Java集合框架,Collection接口,List接口与实现类(ArrayList、Vector、LinkedList)
【Java】(二十一)泛型类/接口/方法/集合,Set接口与实现类(HashSet、TreeSet)
6 Map接口与实现类
- Map接口的特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。
- 集合创建:
HashMap<键值数据类型, 值数据类型> 集合名 = new HashMap<>();
- 方法:
(1)添加对象
v put(K key,v value)
//将对象存入到集合中,关联键值。key重复则覆盖原值。
(2)删除对象:remove()
(3)获取对象(+增强for循环→遍历)
Set<String> keys = map1.keySet();
//返回一个set集合包含所有的键值
map集合名.get(键值)
//根据键获取对应的值。
map集合名.entrySet()
//键值匹配的Set集合。getKey()
和getValue()
分别获取键值。
Collection<V> values()
//返回包含所有值的Collection集合。
(4)判断:containsKey()
和containsValue()
package map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class mapText {
public static void main(String[] args) {
//创建Map集合
HashMap<String, Integer> map1 = new HashMap<>();
System.out.println("1.添加元素");
map1.put("Nike", 1000);
map1.put("Lining", 100);
map1.put("Adidas", 500);
map1.put("Nike", 999);//重复键,值覆盖
System.out.println(map1.size());
System.out.println(map1);
System.out.println("2.删除元素");
map1.remove("Lining");//根据键值删除
System.out.println(map1);
//遍历
System.out.println("3.1通过keySet()获取键值");
Set<String> keys = map1.keySet();//返回一个set集合包含所有的键
for (String key : keys) {
System.out.println("{"+key+","+map1.get(key)+"}");//获取键对应的值
}
System.out.println("3.2通过entrySet()获取<键,值>");
for (Map.Entry<String, Integer> stringIntegerEntry : map1.entrySet()) {
System.out.println("{"+stringIntegerEntry.getKey()+","+stringIntegerEntry.getValue()+"}");
}
System.out.println("4.查询");
System.out.println(map1.containsKey("Nike"));
System.out.println(map1.containsValue(500));
}
}
/*
1.添加元素
3
{Nike=999, Lining=100, Adidas=500}
2.删除元素
{Nike=999, Adidas=500}
3.1通过keySet()获取键值
{Nike,999}
{Adidas,500}
3.2通过entrySet()获取<键,值>
{Nike,999}
{Adidas,500}
4.查询
true
true
*/
6.1 Map集合的实现类
- HashMap【重点】:JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。
- Hashtable:JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
- Properties:Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
- TreeMap:实现了SortedMap接口(是Map的子接口),可以对key自动排序。
6.2 HashMap类
- 存储结构:哈希表(数组+链表+红黑树)
和之前说过的HashSet类似,判断重复依据是hashCode和equals方法,重写即可。【重写之后才能通过new关键字插入或删除集合中相应的对象】 - 查看HashMap的源码分析总结:
(1)HashMap刚创建时,table是null,节省空间,当添加第一个元素时,table容量调整为16。
(2)当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
(3)jdk1.8当每个链表长度>8,并且数组元素个数≥64时,会调整成红黑树,目的是提高效率
(4)jdk1.8当链表长度<6时调整成链表
(5)jdk1.8以前,链表时头插入,之后为尾插入 - HashSet的存储结构就是HashMap。它的add方法调用的就是map的put方法,把元素作为map的key传进去。
一篇写的很好的HashMap源码分析:HashMap源码分析
默认初始化容量:static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16(算术左移)
数组最大容量:static final int MAXIMUM_CAPACITY = 1 << 30;
默认加载因子:static final float DEFAULT_LOAD_FACTOR = 0.75f;
新建Student类:
package map;
import java.util.Objects;
public class Student {
String name;
int number;
public Student() {
}
public Student(String name, int number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", number=" + number +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return number == student.number && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, number);
}
}
使用Student类作为键的HashMap集合:
package map;
import java.util.HashMap;
public class HashMapText {
public static void main(String[] args) {
//创建集合
HashMap<Student, Integer> map = new HashMap<>();
//创建student对象
Student s1 = new Student("a11", 2323);
Student s2 = new Student("a12", 2345);
Student s3 = new Student("a13", 2354);
System.out.println("向集合中添加对象");
map.put(s1, 22);
map.put(s2, 18);
map.put(s3, 20);
map.put(new Student("a12", 2345), 3);//添加重复键,更新值
System.out.println(map);
//删除,遍历,查询和Map一致(不写了)
}
}
/*
向集合中添加对象
{Student{name='a12', number=2345}=3, Student{name='a13', number=2354}=20, Student{name='a11', number=2323}=22}
*/
6.3 TreeMap类
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序。
- 存储结构:红黑树
同样类似TreeSet类,在对象类中实现Comparable接口;或者使用比较器来定制比较。 - TreeSet的存储结构实际上就是TreeMap。它的add方法调用的就是TreeMap的put方法,将元素作为key传入到存储结构中。
7 Collections工具类
- 概念:集合工具类,定义了除了存取以外的集合常用方法。
- 方法:
public static void reverse(List<?> list)/
/反转集合中元素的顺序
public static void shuffle(List<?> list)
//随机重置集合元素的顺序
public static void sort(List<T> list)
//升序排序(元素类型必须实现Comparable接口)
package map;
import java.util.*;
public class UseCollections {
public static void main(String[] args) {
ArrayList<Integer> listset = new ArrayList<>();
listset.add(100);
listset.add(34);
listset.add(25);
listset.add(33);
System.out.println("原始集合ArrayList:"+listset);
Collections.sort(listset);
System.out.println("排序集合ArrayList:"+listset);
int i = Collections.binarySearch(listset, 33);
System.out.println("二分查找33的序列号:"+i);
ArrayList<Integer> list2 = new ArrayList<>();
for (int i1 = 0; i1 < listset.size(); i1++) {//开辟空间
list2.add(0);
}
Collections.copy(list2, listset);
System.out.println("复制集合list2:"+list2);
Collections.reverse(list2);
System.out.println("反转后序列:"+list2);
Collections.shuffle(list2);
System.out.println("打乱:"+list2);
//list转成数组
Integer[] arr=list2.toArray(new Integer[0]);
System.out.println(arr.length);
//数组转成集合
String[] nameStrings= {"LU","MA","YANG"};
List<String> list3 = Arrays.asList(nameStrings);//受限集合,不能添加和删除
// list3.add("aa");//编译报错
System.out.println(list3);
}
}
/*
原始集合ArrayList:[100, 34, 25, 33]
排序集合ArrayList:[25, 33, 34, 100]
二分查找33的序列号:1
复制集合list2:[25, 33, 34, 100]
反转后序列:[100, 34, 33, 25]
打乱:[33, 34, 100, 25]
4
[LU, MA, YANG]
*/