集合-4
1.Map集合概述和特点
* A:Map接口概述
*查看API可以知道:
*将键映射到值的对象
*一个映射不能包含重复的键
*每个键最多只能映射到一个值
* B:Map接口和Collection接口的不同
*Map是双列的,Collection是单列的
*Map的键唯一,Collection的子体系Set是唯一的
*Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
@@set的底层是map
2.Map集合的功能概述
* A:Map集合的功能概述
* a:添加功能
*V put(K key,V value):添加元素。 @@键是唯一的,不可以重复!!!!!!
*如果键是第一次存储,就直接存储元素,返回null
*如果键不是第一次存在,就用值把以前该键的值替换掉,返回以前的值
Map<String,Integer> map = new HashMap<>();
Integeri1 = map.put("张三", 23); @@接收的数据类型为V,Map<K,V>!!!!!
Integeri2= map.put("李四", 24);
Integeri5 = map.put("张三", 26); //相同的键不存储,值覆盖,把被覆盖的值返回!!!
System.out.println(i2); @@以上返回的都是null,因为开始添加前集合里面没有元素,而它返回的是被覆盖掉的值,所以输出都是null!!!!!!
System.out.println(i5); @@输出23,因为集合中有一个张三了,在向集合添加张三,就会覆盖掉原先的张三的值!!!!!!
* b:删除功能
*void clear():移除所有的键值对元素
*V remove(Object key):根据键删除键值对元素,并把值返回
Integer value = map.remove("张三"); //根据键删除元素,返回键对应的值
* c:判断功能
*boolean containsKey(Object key):判断集合是否包含传入的键
*boolean containsValue(Object value):判断集合是否包含传入的值
*boolean isEmpty():判断集合是否为空
* d:获取功能
*Set<Map.Entry<K,V>> entrySet():
//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
*V get(Object key):根据键获取值
*Set<K> keySet():获取(集合中)所有键的集合
*Collection<V> values():获取集合中所有值的集合
*e:长度功能
*int size():返回集合中的键值对的个数
3.Map集合的遍历之键找值 ,不能直接迭代!!!
* A:键找值思路:
*获取所有键的集合
*遍历键的集合,获取到每一个键
*根据键找值
* B:案例演示
*Map集合的遍历之键找值
HashMap<String,Integer> hm = new HashMap<>();
hm.put("张三",23);
hm.put("李四",24);
hm.put("王五",25);
hm.put("赵六",26);
/*Set<String>keySet = hm.keySet(); //获取集合中所有的键
Iterator<String>it = keySet.iterator(); //获取迭代器
while(it.hasNext()){ //判断单列集合中是否有元素
Stringkey = it.next(); //获取集合中的每一个元素,其实就是双列集合中的键
Integervalue = hm.get(key); //根据键获取值
System.out.println(key+ "=" + value); //打印键值对
}*/
for(Stringkey : hm.keySet()) { //增强for循环迭代双列集合第一种方式
System.out.println(key+ "=" + hm.get(key));
}
4.Map集合的遍历之根据键值对对象找键和值 @A@@相比上面的方法效率要高一些!!!!!
* A:键值对对象找键和值思路:
*获取所有键值对对象的集合
*遍历键值对对象的集合,获取到每一个键值对对象
*根据键值对对象找键和值
* B:案例演示
*解释一个Map.Entry
@@Entry是Map中的一个内部接口!!!!!!
*Map集合的遍历之键值对对象找键和值
@@Map.Entry<String,Integer>是键值对对象,map.entrySet())是键值对集合!!!!!!
HashMap<String,Integer> hm = new HashMap<>();
hm.put("张三",23);
hm.put("李四",24);
hm.put("王五",25);
hm.put("赵六",26);
/*Set<Map.Entry<String,Integer>> entrySet = hm.entrySet(); //获取所有的键值对象的集合
Iterator<Entry<String,Integer>> it = entrySet.iterator();//获取迭代器
while(it.hasNext()){
Map.Entry<String, Integer> en =it.next(); //父类引用指向子类对象
//Entry<String,Integer> en = it.next(); //直接获取的是子类对象
Stringkey = en.getKey(); //根据键值对对象获取键
Integervalue = en.getValue(); //根据键值对对象获取值
System.out.println(key+ "=" + value);
}*/
for(Entry<String,Integer>en : hm.entrySet()) {
System.out.println(en.getKey()+ "=" + en.getValue());
}
5.HashMap集合键是Student值是String的案例
* A:案例演示
*HashMap集合键是Student值是String的案例
@@当键是自定义对象的时候,必须重写hashcode和equals方法,否则不会覆盖键值相同的对象,不能保证键值的唯一!!!!!!
6.LinkedHashMap的概述和使用
* A:LinkedHashMap的特点
*底层是链表实现的可以保证怎么存就怎么取
7.TreeMap集合键是Student,值是String的案例 TreeMap可以实现排序!!!!!!!!!
* A:案例演示
*TreeMap集合键是Student值是String的案例
@@Student这个类必须实现comparable接口,并重写comparaTo方法,或者采用比较器才可以,和TreeSet时是一样的!!!
publicstatic void main(String[] args) {
//demo1();
TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
@Override
publicint compare(Student s1, Student s2) {
intnum = s1.getName().compareTo(s2.getName()); //按照姓名比较,姓名是根据Unicode码表来比较的!!!!!!
returnnum == 0 ? s1.getAge() - s2.getAge() : num;
}
});
tm.put(newStudent("张三", 23), "北京");
tm.put(newStudent("李四", 13), "上海");
tm.put(newStudent("赵六", 43), "深圳");
tm.put(newStudent("王五", 33), "广州");
System.out.println(tm);
}
publicstatic void demo1() {
TreeMap<Student,String> tm = new TreeMap<>();
tm.put(newStudent("张三", 23), "北京");
tm.put(newStudent("李四", 13), "上海");
tm.put(newStudent("王五", 33), "广州");
tm.put(newStudent("赵六", 43), "深圳");
System.out.println(tm);
}
}
8.统计字符串中每个字符出现的次数
* A:案例演示
*需求:统计字符串中每个字符出现的次数
*分析:
* 1,定义一个需要被统计字符的字符串
* 2,将字符串转换为字符数组
* 3,定义双列集合,存储字符串中字符以及字符出现的次数
* 4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
* 5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
* 6,打印双列集合获取字符出现的次数
Stringstr = "aaaabbbcccccccccc";
char[]arr = str.toCharArray(); //将字符串转换成字符数组
HashMap<Character,Integer> hm = new HashMap<>(); //创建双列集合存储键和值
for(charc : arr) { //遍历字符数组
/*if(!hm.containsKey(c)){ //如果不包含这个键
hm.put(c, 1); //就将键和值为1添加
}else{ //如果包含这个键
hm.put(c,hm.get(c) + 1); //就将键和值再加1添加进来
}
//hm.put(c,!hm.containsKey(c) ? 1 : hm.get(c) + 1);
Integeri = !hm.containsKey(c) ? hm.put(c, 1) : hm.put(c, hm.get(c) + 1);
}
for(Character key : hm.keySet()) { //遍历双列集合
System.out.println(key+ "=" + hm.get(key));
}
9.集合嵌套之HashMap嵌套HashMap
* A:案例演示
*集合嵌套之HashMap嵌套HashMap
publicstatic void main(String[] args) {
//定义88期基础班
HashMap<Student,String> hm88 = new HashMap<>();
hm88.put(newStudent("张三", 23), "北京");
hm88.put(newStudent("赵六", 26), "广州");
//定义99期基础班
HashMap<Student,String> hm99 = new HashMap<>();
hm99.put(newStudent("唐僧", 1023), "北京");
hm99.put(newStudent("孙悟空",1024), "北京");
//定义双元课堂
HashMap<HashMap<Student,String>, String> hm = new HashMap<>();
hm.put(hm88,"第88期基础班");
hm.put(hm99,"第99期基础班");
//遍历双列集合
for(HashMap<Student,String> h : hm.keySet()) { //hm.keySet()代表的是双列集合中键的集合
Stringvalue = hm.get(h); //get(h)根据键对象获取值对象
//遍历键的双列集合对象
for(Studentkey : h.keySet()) { //h.keySet()获取集合总所有的学生键对象
Stringvalue2 = h.get(key);
System.out.println(key+ "=" + value2 + "=" + value);
}
}
}
}
10.(HashMap和Hashtable(就向vector一样都是JDK1.0出现的,但都被替代掉了)的区别
* A:面试题
*HashMap和Hashtable的区别
*Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
*Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
*共同点:
* 底层都是哈希算法,都是双列集合
* B:案例演示
*HashMap和Hashtable的区别
11.Collections工具类的概述和常见方法讲解
@@Arrays工具类是操作数组的,Collections工具类是操作集合的!!!!!!!!!!
* A:Collections类概述
*针对集合操作 的工具类
* B:Collections成员方法
publicstatic <T> void sort(List<T> list)
ArrayList<String> list = newArrayList<>();
list.add("c");
list.add("a");
list.add("a");
list.add("b");
Collections.sort(list); //将集合排序
System.out.println(list); a,a,b,c,d
publicstatic <T> int binarySearch(List<?> list,T key) //二分查找法
publicstatic <T> T max(Collection<?> coll)
publicstatic void reverse(List<?> list)
publicstatic void shuffle(List<?> list)
ArrayList<String> list = newArrayList<>();
list.add("a");
list.add("c");
list.add("d");
//System.out.println(Collections.max(list)); //根据默认排序结果获取集合中的最大值 d
//Collections.reverse(list); //反转集合
Collections.shuffle(list); //随机置换,可以用来洗牌,每次运行结果都不相同!!!!!
System.out.println(list);
12.模拟斗地主洗牌和发牌
* A:案例演示,模拟斗地主洗牌和发牌,牌没有排序
//买一副扑克
String[]num ={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[]color = {"方片","梅花","红桃","黑桃"};
ArrayList<String>poker = new ArrayList<>();
for(Strings1 : color) {
for(Strings2 : num) {
poker.add(s1.concat(s2));
}
}
poker.add("小王");
poker.add("大王");
//洗牌
Collections.shuffle(poker);
//发牌
ArrayList<String>gaojin = new ArrayList<>();
ArrayList<String>longwu = new ArrayList<>();
ArrayList<String>me = new ArrayList<>();
ArrayList<String>dipai = new ArrayList<>();
for(inti = 0; i < poker.size(); i++) {
if(i>= poker.size() - 3) {
dipai.add(poker.get(i));
}elseif(i % 3 == 0) {
gaojin.add(poker.get(i));
}elseif(i % 3 == 1) {
longwu.add(poker.get(i));
}else{
me.add(poker.get(i));
}
}
//看牌
System.out.println(gaojin);
System.out.println(longwu);
System.out.println(me);
System.out.println(dipai);
13.模拟斗地主洗牌和发牌并对牌进行排序的代码实现
//买一副牌
String[]num ={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[]color = {"方片","梅花","红桃","黑桃"};
HashMap<Integer,String> hm = new HashMap<>(); //存储索引和扑克牌
ArrayList<Integer>list = new ArrayList<>(); //存储索引
intindex = 0; //索引的开始值
for(Strings1 : num) {
for(Strings2 : color) {
hm.put(index,s2.concat(s1)); //将索引和扑克牌添加到HashMap中
list.add(index); //将索引添加到ArrayList集合中
index++;
}
}
hm.put(index,"小王");
list.add(index);
index++;
hm.put(index,"大王");
list.add(index);
//洗牌
Collections.shuffle(list);
//发牌
TreeSet<Integer>gaojin = new TreeSet<>();
TreeSet<Integer>longwu = new TreeSet<>();
TreeSet<Integer>me = new TreeSet<>();
TreeSet<Integer>dipai = new TreeSet<>();
for(inti = 0; i < list.size(); i++) {
if(i>= list.size() - 3) {
dipai.add(list.get(i));//将list集合中的索引添加到TreeSet集合中会自动排序
}elseif(i % 3 == 0) {
gaojin.add(list.get(i));
}elseif(i % 3 == 1) {
longwu.add(list.get(i));
}else{
me.add(list.get(i));
}
}
//看牌
lookPoker("高进",gaojin, hm);
lookPoker("龙五",longwu, hm);
lookPoker("冯佳", me,hm);
lookPoker("底牌",dipai, hm);
}
publicstatic void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm) {
System.out.print(name+ "的牌是:");
for(Integer index : ts) {
System.out.print(hm.get(index)+ " ");
}
System.out.println();
}
14.集合框架(泛型固定下边界)
* 泛型固定下边界
* ? super E
*
* 泛型固定上边界
* ? extends E
15.总结
* Collection
* List(存取有序,有索引,可以重复)
* ArrayList
* 底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
* LinkedList
* 底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
* Vector
* 底层是数组实现的,线程安全的,无论增删改查都慢
* 如果查找和修改多,用ArrayList
* 如果增和删多,用LinkedList
* 如果都多,用ArrayList
* Set(存取无序,无索引,不可以重复)
* HashSet
* 底层是哈希算法实现
* LinkedHashSet
* 底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
* TreeSet
* 底层是二叉树算法实现
* 一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高
* TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别
* Map
* HashMap
* 底层是哈希算法,针对键
* LinkedHashMap
* 底层是链表,针对键
* TreeMap
* 底层是二叉树算法,针对键
* 开发中用HashMap比较多