双列集合
(一)Map接口的常用功能
1、概述
Map<K,V>是一个泛型接口,是双列集合的顶层接口,定义了所有双列集合的功能和遍历方式
双列集合:就是一个用来存放多个键值对数据的容器,双列:一列是键,一列是值,键和值都是成对出现的。
Map中文这里是映射的含义
键值对:一对一的映射关系的一对数据,映射的意思就是可以通过一个值找到另一个值得意思,在Map集合中含义就是可以通过Key值找到Value值
2、Map存储键值对特点
①存放的是键值对数据
②无序集合
③键要唯一 key值不能出现重复的,value值可以重复。
3、Map接口中常用的方法
import java.util.HashMap;
import java.util.Map;
public class Demo01 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("name","fsf");
map.put("age","19");
//添加
map.put("gender","man");
System.out.println(map);
map.put("name","tom");
System.out.println(map);
//删除
//返回被删除的元素
System.out.println(map.remove("name"));
//获取对应的值
System.out.println(map.get("gender"));
//是否包含某个键
System.out.println(map.containsKey("aaa"));
//判断是否包含某个Value值
System.out.println(map.containsValue("19"));
//返回元素数
System.out.println(map.size());
//清空
map.clear();
//判断是否为空
System.out.println(map.isEmpty());
}
}
(二)Map集合的遍历方式
1、键遍历(键找值遍历)
Map集合不能直接遍历,把Map集合转变为单列集合(存储这所有的key值得单列集合),通过遍历单列集合间接的获取Map集合的键值对数据
方法:
keySet():获取所有的键,形成一个set集合
get(K key):通过键获取对应值
步骤:
①通过keySet方法把Map集合所有key获取到,存储到set集合
②遍历set集合获取每一个key值
③Map集合get(K key),得到对应的value
代码:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo01 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("max",100);
map.put("mid",50);
map.put("min",30);
Set<String> keys = map.keySet();
System.out.println(keys);
for (String key : keys) {
System.out.println(key+"=="+map.get(key));
}
}
}
2、值遍历(不是map遍历)
方法:values():可以获取集合中所有的值,形成一个单独的集合
只能得到所有的值,没法通过值找到对应的键,只能是map的值获取,不能实现键值对的遍历
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class Demo02 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("1","张三");
map.put("2","李四");
map.put("3","王五");
map.put("4","赵六");
Collection<String> c = map.values();
for (String s : c) {
System.out.println(s);
}
}
}
3、键值对遍历
方法:
entrySet():把双列集合每个键值对转换为Entry对象,再把Entry放到set集合中-------Map集合的方法
Entry是Map接口内部定义的一个接口,我们不需要关心怎么生成接口实现类,Map集合调用 entrySet方法,方法内部就会根据键值对生成Entry接口实现类对象。
Entry对象的方法:
getKey():获取Entry对象的key值(其实就是Map对象的key值)--------Entry接口方法
getValue():获取Entry对象的Value值(其实就是map集合的value值)------Entry接口的方法
步骤:
①通过entrySet方法把map集合转变为Entry对象的Set集合
②遍历Set集合得到每一个Entry对象
③通过Entry的getKey和getValue方法分别得到key值和value值
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo03 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("1","张三");
map.put("2","李四");
map.put("3","王五");
map.put("4","赵六");
//调用entrySet()返回一个Set集合中储存根据Map集合键值对数据封装成entry对象
Set<Map.Entry<String, String>> set = map.entrySet();
//遍历set集合
for (Map.Entry<String, String> en : set) {
String key = en.getKey();
String value = en.getValue();
System.out.println(key+"==="+value);
}
}
}
(三)Map常用的实现类介绍
HashMap<K,V>:存储数据采用的是哈希表结构,元素的存取顺序不能保证一致。
由于要保证键的唯一、不重复,如果自定义类型数据当做Key值,要保证唯一和不重复,需要重写键的hashCode()方法、equals()方法。JDK提供类型不需要重写。
HashMap和Hashtable的区别
1、出现的时机不一样
HashMap是jdk1.2出现的
Hashtable是jdk1.0出现
2、线程安全不一样
HashMap是线程不安全的
Hashtable是线程安全的
3、效率不一样
HashMap效率高
Hashtable是线程安全的
4、存放数据要求不一样
HashMap是支持null值和null键
Hashtable不支持null数据
5、HashMap和Hashtable有相同的API。
HashMap和HashSet的关系
HashSet的底层是由HashMap构建的
HashSet的存值元素唯一原理就是HashMap的存key值唯一原理
创建HashSet集合的时候其实创建了一个HashMap集合
HashSet集合add方法添加元素的时候底层调用HashMap的put方法添加到Map集合
添加的时候如果key已经在HashMap中储存,会使用新添加的键值对中的value值,把原来的key值得value值覆盖掉
练习:
键盘录入一个字符串,统计每个字符出现的次数
例如:录入aaaabbccddd!@#@#$@#$%cc66ff
打印出来:a 有 4 个,b 有 2 个,c 有 4 个,d 有 3 个,! 有 1 个,@ 有 3 个,$ 有 2 个,% 有 1 个,6 有 2个,f 有 2 个
package com.offcn.demo03;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
HashMap<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if(map.containsKey(s.charAt(i))){
Integer a = map.get(s.charAt(i));
a++;
map.put(s.charAt(i),a);
}else {
map.put(s.charAt(i),1);
}
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<Character,Integer> en : map.entrySet()){
sb.append(en.getKey()+"有").append(en.getValue()+"个");
}
System.out.println(sb);
}
}
LinkedHashMap
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的
hashCode()方法、equals()方法。
特点:有序的Map集合,key值唯一,都可以存放键的值为null.
import java.util.LinkedHashMap;
public class Demo01 {
public static void main(String[] args) {
LinkedHashMap<String,String> map = new LinkedHashMap<>();
map.put("1","张三");
map.put("2","李四");
map.put("3","王五");
map.put("3","赵六");
map.put(null,null);
System.out.println(map);
}
}
TreeMap(了解)
该集合可以根据其存储键值对的key值自然顺序进行排序,或者根据创建Map集合时提供的 Comparator 进行排序,具体取决于使用的构造方法。
自然排序: 键(key)所属的类型要实现Comparable接口.
比较器排序:创建TreeMap对象是传入一个比较器,根据比较器的规则对key进行排序.
Collections工具类
(一)可变参数的使用和注意事项
1、概述
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了.,
使用场景: 方法的参数类型已经确定, 个数不确定, 我们可以使用可变参数.
【相同类型的多个形参的方法的参数列表变形】 (int a, int b, int c, int d, ) --> (int...a)
2、格式
修饰符 返回值类型 方法名(数据类型1 参数名1, 数据类型2 参数名2, 数据类型n… 参数名n) {
可变参数名在方法体中,把它当做数组名来操作.
}
调用带有可变参数的方法时,可以传入0~n个实参给可变参数赋值.
3、注意事项
1.这里的可变参数名其实是一个数组名
2.如果一个方法有多个参数,包含可变参数,可变参数要放在最后,否则编译报错
3.一个方法中只能使用一个可变参数,否则编译报错
package com.offcn.demo05;
public class Demo01 {
public static void main(String[] args) {
System.out.println(getSum(10,10,10,10,10,10,10));
printNum(1.0,2.0f,1,2,3,4,5);
}
public static int getSum(int... a){
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
public static void printNum(double a,float b,int... c){
System.out.println(a);
System.out.println(b);
for (int i = 0; i < c.length; i++) {
System.out.println(c[i]);
}
}
}
(二)Collections常用功能
1、概述
Collections类是和一个工具类,在类中封装类很多常用的操作集合的方法. 它不止能操作单列集合,也能操作双列集合.
1.不能创建对象
2.类中内容都是静态的(静态属性和静态方法)
2、常用方法
package com.offcn.demo05;
import java.util.ArrayList;
import java.util.Collections;
public class Demo02 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(59);
list.add(10);
list.add(79);
list.add(15);
list.add(45);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
}