一.Map集合
1.概念:表示键值对应关系的数据,提供key到value的映射。Map中不能包含有相同的key,每个key只能映射一个value,当相同的key对应多个value时,后面的value会把前面的覆盖。Map集合包括Map接口以及Map接口的所有实现类。
2.子实现类:根接口Map<K,V>,主要的实现类包括:HashMap、TreeMap、LinkedHashMap、Hashtable.重点掌握前两个。
3.添加功能:
put(K key,V value):向集合中添加指定的key与value的映射关系
特点:第一次存储,返回的值是null.第二次存储键相同的数据,会返回上一次的值,在集合中后面添加的键对应的值会把前一次键对应的值覆盖掉。
4.删除功能:
void clear():移除所有的键值对元素
V remove(Object key):根据键,从集合中移除这个键值对,返回键对应的值
5.判断功能:
boolean containskey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
6.获取功能:
Set<Map.Entry<K,V>>entrySet():返回一个键值对的Set集合
Set<K> keySet():获取集合中所有键的集合
V get<Object key>:获取集合中键对应的值,如果键不存在,则返回null
Collection<V>values():返回该集合中所有值对象形成的Collection集合
7.Map集合的底层数据结构只和键有关,和值无关,集合中的元素唯一性由hashCode()和equals()保证,在自定义对象中,若不重写这两个方法,就不能保证唯一性。
package day_16_11_18.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map <Integer,String> map = new HashMap<Integer,String>();
//给集合添加元素
String str = map.put(101,"张");
System.out.println(str); //null
String str2 = map.put(101, "罗");
System.out.println("str2:"+str2); //张,两个键相同时,第二个返回第一个键对应的值
map.put(102, "赵");
map.put(103, "李");
map.put(104, "刘");
map.put(105, "王");
//输出集合元素
System.out.println(map); //{101=罗, 102=赵, 103=李, 104=刘, 105=王}
//删除功能
//map.clear();
//System.out.println(map); //{}
String str3 = map.remove(101); //返回删除键对应的值
System.out.println("str3:"+str3); //str3:罗,键相同,把之前键对应的值覆盖了
//遍历
//方式1:根据键获取值Set<k> keySet()
Set<Integer> keySet = map.keySet();
for(Integer key : keySet){
System.out.println(key+"-----"+map.get(key));
}
System.out.println("---------");
//方式2:Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
Set<java.util.Map.Entry<Integer, String>> entrySet = map.entrySet();
for(java.util.Map.Entry<Integer, String> en : entrySet){
System.out.println(en.getKey()+"-----"+en.getValue());
}
System.out.println("---------");
//方式3: Collection<V> values():获取集合中所有值的集合
Collection<String> values = map.values();
for(String v :values){
System.out.println(v);
}
}
}
二.HashMap集合
1.底层数据结构是哈希表,特点是元素唯一无序性,唯一性由hashCode()和equals()方法保证。允许使用null值和null键,但必须保证键的唯一性。HashMap通过哈希表对其内部的映射关系进行快速查找。不保证映射的顺序,并且不保证该顺序恒久不变。
package day_16_11_18.treemap;
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
// 创建HashMap对象
HashMap<String,Student> hm = new HashMap<String,Student>();
//创建Student对象
Student s1 = new Student("101","韩庚");
Student s2 = new Student("112","鹿晗");
Student s3 = new Student("201","杨颖");
Student s4 = new Student("231","邓超");
Student s5 = new Student("331","李晨");
Student s6 = new Student("201","杨颖");
//给集合添加元素
hm.put("101", s1);
hm.put("112", s2);
hm.put("201", s3);
hm.put("231", s4);
hm.put("331", s5);
hm.put("201", s6);
//遍历集合中的元素keySet()
Set<String> keySet = hm.keySet();
for(String key : keySet){
//System.out.println(key+"----"+hm.get(key).getName()+" "+hm.get(key).getId());
System.out.println(key+"----"+hm.get(key));//需要在自定义对象的类中重写toString();
}
}
}
package day_16_11_18.treemap;
public class Student {
private String id;
private String name;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
三.TreeMap集合
1.底层数据结构是红黑树,特点是元素唯一,而且还可以对元素进行排序:自然排序、比较器排序。TreeMap不允许使用null键,因为TreeMap类实现Map集合中的映射关系是根据键对象按一定顺序排列的,可以使用null值。
2.实现排序:是因为实现了Comparable接口,并且重写CompareTo()方法。集合中的映射关系具有一定的顺序性,在添加、删除和定位映射关系时,TreeMap类比HashMap性能稍差。
package day_16_11_18.treemap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import day_16_11_18.hashmap.Student;
public class TreeMapDemo {
public static void main(String[] args) {
//创建TreeMap对象
TreeMap<String,Student> tm = new TreeMap<String,Student>();
//创建Student对象
Student s1 = new Student("101","韩庚");
Student s2 = new Student("112","鹿晗");
Student s3 = new Student("201","杨颖");
Student s4 = new Student("231","邓超");
Student s5 = new Student("331","李晨");
Student s6 = new Student("201","杨颖");
//给集合添加元素
tm.put("101", s1);
tm.put("112", s2);
tm.put("231", s4);
tm.put("201", s3);
//tm.put("231", s4);
tm.put("331", s5);
tm.put("201", s6);
//遍历集合元素entrySet()
Set<Entry<String, Student>> entrySet = tm.entrySet();
for(Entry<String, Student> en : entrySet){
String key = en.getKey();
Student value = en.getValue();
System.out.println(key+"-----"+value);
}
}
}
分析:上例中的键是String类型,已经重写了compareTo()方法,如果键是Student类型,要想实现排序,必须Student类实现Comparable接口,并重写compareTo方法来实现对集合的排序。compareTo()方法中的逻辑由自己写。
四.LinkedHashMap集合
底层的数据结构由哈希表和链表来实现,具有可预知的迭代顺序,链表保证了元素的有序,即存储和取出一致,哈希表保证元素的唯一性。
五.HashMap和Hashtable的区别
HashMap非同步,效率高;Hashtable同步,效率低,数据安全。
练习1:
package day_16_11_18.hashmap;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
/**
* @author Luna
* 案例演示: 需求:用户随便输入一段字符串 统计字符串中每个字符出现的次数
* "aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
*
* @param args
*/
public class HashMapTest {
public static void main(String[] args) {
// 创建集合对象
HashMap<Character,Integer> hm = new HashMap<Character,Integer>();
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//录入并接收字符串
System.out.println("请输入一段字符串:");
String str = sc.nextLine();
//将字符串转化成字符数组
char[] chs = str.toCharArray();
//遍历字符数组
for(Character key : chs ){
//注意集合中键值的特性,如果键值对是第一次存入集合,键对应的值是null
//获取键对应的值
Integer value = hm.get(key);
//统计键出现的次数,如果键对应的值是null即第一次出现,令value=1
if(value == null){
hm.put(key, 1);
}else{
value++;
hm.put(key, value);
}
}
//至此已将元素添加进集合
//System.out.println(hm);
//将元素按指定格式输出
Set<Character> keySet = hm.keySet();
for(Character key : keySet){
//创建StringBuilder对象
StringBuilder sb = new StringBuilder();
System.out.println(sb.append(key).append("(").append(hm.get(key)).append(")"));
}
}
}
六.集合工具类Collections
常用方法:
1. public static <T> void sort(List<T> list): 排序,默认按照自然顺序
2.public static <T> int binarySearch(List<?> list,T key): 二分查找
3.public static <T>T max(Collection<?> coll): 获取最大值
4.public static void reverse(List<?> list): 反转
5.public static void shuffle(List<?> list): 随机置换
package day_16_11_18.utils;
import java.util.ArrayList;
import java.util.Collections;
public class CollectionUtils {
public static void main(String[] args) {
// 创建集合对象
ArrayList<Integer> list = new ArrayList<Integer>();
//给集合添加元素
list.add(20);
list.add(18);
list.add(12);
list.add(23);
list.add(10);
//对集合元素进行排序
Collections.sort(list);
for(Integer i : list){
System.out.print(i+" ");
}
System.out.println();
//public static <T> int binarySearch(List<?> list,T key): 二分查找
int search = Collections.binarySearch(list, 18);
System.out.println(search);
//public static <T> T max(Collection<?> coll): 获取最大值
System.out.println("max:"+Collections.max(list));
System.out.println("min:"+Collections.min(list));
//public static void reverse(List<?> list): 反转
Collections.reverse(list);
System.out.println("reverse:"+list);
//public static void shuffle(List<?> list): 随机置换
Collections.shuffle(list);
System.out.println("shuffle:"+list);
}
}
练习:集合的嵌套
HashMap嵌套HashMap
package day_16_11_18.test;
import java.util.HashMap;
import java.util.Set;
/**
* 基础班
* 张三 ---20
* 李四 ---22
* 就业班
* 王五--- 21
* 赵六 ---23
*
*/
public class HmToHm {
public static void main(String[] args) {
// 创建两个小的HashMap对象
HashMap<String,Integer> basicHm = new HashMap<String,Integer>();
HashMap<String,Integer> jobHm = new HashMap<String,Integer>();
//给小集合添加元素
basicHm.put("张三", 20);
basicHm.put("李四", 22);
jobHm.put("王五", 21);
jobHm.put("赵六", 23);
//创建一个大的集合
HashMap<String, HashMap<String, Integer>> bigHm = new HashMap<String,HashMap<String,Integer>>();
//将小集合添加到大集合中
bigHm.put("基础班", basicHm);
bigHm.put("就业班", jobHm);
//嵌套的集合遍历
//获取键
Set<String> keySet = bigHm.keySet();
for(String key : keySet){
System.out.println(key); //大集合的键
//取出小集合,即大集合中键对应的值
HashMap<String, Integer> minHm = bigHm.get(key);
//获取键
Set<String> minkeySet = minHm.keySet();
for(String minKey : minkeySet){
System.out.println("\t"+minKey+"----"+minHm.get(minKey));
}
}
}
}
HashMap嵌套ArrayList
package day_16_11_18.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
/**
* @author Luna
*三国演义
吕布
周瑜
*笑傲江湖
令狐冲
林平之
*神雕侠侣
郭靖
杨过
*2017年11月21日
*/
public class HmToArraylist {
public static void main(String[] args) {
//创建ArrayList集合
ArrayList<String> SgArry = new ArrayList<String>();
//给集合添加元素
SgArry.add("吕布");
SgArry.add("周瑜");
ArrayList<String> XaArry = new ArrayList<String>();
//给集合添加元素
XaArry.add("吕布");
XaArry.add("周瑜");
ArrayList<String> SdArry = new ArrayList<String>();
//给集合添加元素
SdArry.add("吕布");
SdArry.add("周瑜");
//创建HashMap集合对象
HashMap<String, ArrayList<String>> hm = new HashMap<String,ArrayList<String>>();
//给集合添加元素
hm.put("三国演义", SgArry);
hm.put("笑傲江湖", XaArry);
hm.put("神雕侠侣", SdArry);
//遍历集合
Set<String> keySet = hm.keySet();
for(String key : keySet){
System.out.println(key);
//获取键对应的值,即ArrayList集合
ArrayList<String> arry = hm.get(key);
//遍历ArrayList集合
for(String s : arry ){
System.out.println("\t"+""+s);
}
}
}
}
ArrayList嵌套HashMap
package day_16_11_18.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
/**
* @author Luna
* 周瑜---小乔
吕布---貂蝉
郭靖---黄蓉
杨过---小龙女
令狐冲---任盈盈
林平之---岳灵珊
*2017年11月21日
*/
public class ArrayListToHm {
public static void main(String[] args) {
// 创建三个HashMap集合对象
HashMap<String, String> hm1 = new HashMap<String,String>();
hm1.put("周瑜", "小乔");
hm1.put("吕布", "貂蝉");
HashMap<String, String> hm2 = new HashMap<String,String>();
hm2.put("郭靖", "黄蓉");
hm2.put("杨过", "小龙女");
HashMap<String, String> hm3 = new HashMap<String,String>();
hm3.put("令狐冲", "任盈盈");
hm3.put("林平之", "岳灵珊");
//创建大的ArrayList集合对象
ArrayList<HashMap<String, String>> arry = new ArrayList<HashMap<String, String>>();
arry.add(hm1);
arry.add(hm2);
arry.add(hm3);
//遍历集合
for(HashMap<String, String> hm : arry){
//System.out.println(hm);
//获取键的集合
Set<String> keySet = hm.keySet();
for(String key : keySet){
System.out.println(key+"----"+hm.get(key));
}
System.out.println();
}
}
}
练习:
package day_16_11_18.test;
import java.util.ArrayList;
import java.util.Collections;
/**
* 需求:斗地主实现发牌和看牌
*分析:1.定义两个字符串数组,存放牌的花色和牌
* 2.定义一个集合,存放所有的牌
* 3.数组循环遍历,添加到集合当中,生成一副牌
* 4.用集合工具类中的shuffle()方法进行洗牌
* 5.发牌:三个人 一副底牌,需要创建四个集合
*2017年11月22日
*/
public class PokerGame {
public static void main(String[] args) {
// 创建一个集合,存放所有的牌
ArrayList<String> poxBox = new ArrayList<String>();
//定义一个数组存放所有的花色
String [] colors = {"♠","♥","♦","♣"};
//定义一个数组存放所有的数字
String [] nums = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
//双重遍历数组生成牌添加到牌盒
for(int i=0;i<colors.length;i++){
for(int j=0;j<nums.length;j++){
poxBox.add(colors[i]+nums[j]);
}
}
//添加大小王
poxBox.add("☀");
poxBox.add("⊙");
//洗三次牌
Collections.shuffle(poxBox);
Collections.shuffle(poxBox);
Collections.shuffle(poxBox);
//三个人,一副底牌,定义四个集合
ArrayList<String> first = new ArrayList<String>();
ArrayList<String> second = new ArrayList<String>();
ArrayList<String> third = new ArrayList<String>();
ArrayList<String> endCard = new ArrayList<String>();
//发牌
for(int i=0;i<poxBox.size();i++){
//进行判断,底牌流三张
if(i>=poxBox.size()-3){
endCard.add(poxBox.get(i));
}else if(i%3==0){
first.add(poxBox.get(i));
}else if(i%3==1){
second.add(poxBox.get(i));
}else if(i%3==2){
third.add(poxBox.get(i));
}
}
//看牌
lookPoker("first",first);
lookPoker("second",second);
lookPoker("third",third);
lookPoker("endCard",endCard);
}
private static void lookPoker(String name, ArrayList<String> list) {
System.out.println(name);
for(String poker : list){
System.out.print(poker+" ");
}
System.out.println();
}
}
改进版
package day_16_11_18.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
/**
* 斗地主游戏发牌 洗牌的改进版:使用双列集合,一张牌对应一个索引,发牌洗牌都是对索引的操作
*
*2017年11月22日
*/
public class NewPokerGame {
public static void main(String[] args) {
HashMap<Integer, String> pokBox = new HashMap<Integer,String>();
//生成一副牌
//定义一个数组存放所有的花色
String [] colors = {"♠","♥","♦","♣"};
//定义一个数组存放所有的数字
String [] nums = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
//定义一个集合,存放牌的索引
ArrayList<Integer> indexs = new ArrayList<Integer>();
int index = 0;
for(String num : nums){
for(String color : colors){
pokBox.put(index, num + color);
indexs.add(index);
index++;
}
}
//添加大小王
//System.out.println(index);
indexs.add(index);
pokBox.put(index, "☀");
index++;
indexs.add(index);
pokBox.put(index, "⊙");
// System.out.println(index);
//洗牌 就是洗索引集合
Collections.shuffle(indexs);
Collections.shuffle(indexs);
Collections.shuffle(indexs);
//发牌,发牌的索引
TreeSet<Integer> first = new TreeSet<Integer>();
TreeSet<Integer> second = new TreeSet<Integer>();
TreeSet<Integer> third = new TreeSet<Integer>();
TreeSet<Integer> endCard = new TreeSet<Integer>();
//发牌
for(int i=0;i<indexs.size();i++){
//进行判断,底牌流三张
if(i>=indexs.size()-3){
endCard.add(indexs.get(i));
}else if(i%3==0){
first.add(indexs.get(i));
}else if(i%3==1){
second.add(indexs.get(i));
}else if(i%3==2){
third.add(indexs.get(i));
}
}
//看牌
lookPoker("first",first,pokBox);
lookPoker("second",second,pokBox);
lookPoker("third",third,pokBox);
lookPoker("endCard",endCard,pokBox);
}
private static void lookPoker(String name, TreeSet<Integer> list, HashMap<Integer, String> pokBox) {
System.out.println(name);
//看牌,通过索引去找值
for(Integer i : list){
String poker = pokBox.get(i);
System.out.print(poker + " ");
}
System.out.println();
}
}