Map集合:
java.util.Map<k,v>集合
双列结合,夫妻制,一个元素包含两个值(一个key,一个value)
map集合中的元素,key和value的数据类型可以相同,也可以不同
map集合中的元素key是不允许重复的,value是可以重复的
键值对,键不可以重复,但是值可以重复。
一个键只能对应一个值,但是一个值可以对应多个键。
map集合的元素,key和value一一对应
常用:
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap底层是哈希表,查询的速度特别快
jdk1.8之前:数组+单向链表
jdk1.8之后:数组+单向链表/红黑树(链表的长度超过8):提高查询的速度
hashMap集合是一个无序的集合,存储元素和取出元素的顺序可能不一致
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap的特点:
LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
LinkedHashMap集合是一个有序的集合,,存储和取出的顺序是一致的
============================
public class MapCls {
public static void main(String[] args) {
show01();
// show02();
// show03();
// show04();
}
/*
* public V put (K key, V value):把指定的键与指定的值添加到集合中
* 返回值:v
* 存储键值对的时候,key不重复,返回值v是null
* 存储键值对的时候,key重复,会使用新的 value 替换 map 中重复的value 返回被替换的value
*
*/
public static void show01(){
//创建,多态,指向实现类,父类是一个接口,接口只能通过他的实现类来完成。
Map<String,String> map = new HashMap<>();
String v1 = map.put("寒冰", "蛮王");
System.out.println(v1);//null,存储的时候key不重复,返回为null
String v2 = map.put("寒冰", "蛮王2");
System.out.println(v2);//返回被替换的蛮王
//value可以重复
map.put("杨过", "小龙女");
map.put("引志平", "小龙女");
System.out.println(map);
}
/*
* public V remove (Object key):把指定的键,所对应的键值对元素,在map集合中删除,返回被删除元素的值
* 返回值:
* key存在,v返回被删除的值
* key不存在,v返回空null
*/
public static void show02(){
//创建
Map<String,Integer> map = new HashMap<>();
map.put("迪丽热巴", 168);
map.put("古力娜扎", 170);
System.out.println(map);
Integer v1 = map.remove("迪丽热巴");
System.out.println(v1);
//没有对应的值,返回空,上面已经删除了.
Integer v2 = map.remove("迪丽热巴");
System.out.println(v2);
}
/*
* public V get (Object key):根据指定的键,在Map集合中获取对应的值
* 返回值:
* key存在,返回对应的value的值
* key不存在,返回null
*
*/
public static void show03(){
//创建Map集合对象
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("杨颖", 165);
map.put("范冰冰", 170);
Integer v1 = map.get("范冰冰");
//返回对应的值
System.out.println(v1);//170
//没有对应的值,返回空
Integer v2 = map.get("小龙女");
System.out.println(v2);//
}
/*
* 判断集合中的键是否存在。
* boolean containsKey(Object key) 判断集合中是否包含指定的键
* 包含则返回true,不包含则返回false
*
*/
public static void show04(){
//创建集合,添加元素。
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("杨颖", 165);
map.put("范冰冰", 170);
boolean b1 = map.containsKey("赵丽颖");
System.out.println(b1);
boolean b2 = map.containsKey("赵颖");
System.out.println(b2);
}
}
HashMap
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map接口的哈希表和链接列表实现具有可预知的迭代顺序,有序的集合LinkedHashMap<K,V>
底层原理:
哈希表+链表(记录元素的顺序)
因为键是唯一的但是值不是,当键冲突的时候,下面的值会替换掉上面的值,为止摆键首次出现的地方。
================================
import java.util.HashMap;
import java.util.LinkedHashMap;
public class LinkedHashMapCls {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("a", "a");
map.put("c", "c");
map.put("b", "b");
map.put("a", "d");
System.out.println(map);//无序的集合
System.out.println("--------------------------------------");
LinkedHashMap<String, String> linked = new LinkedHashMap<>();
linked.put("a", "a");
linked.put("c", "c");
linked.put("b", "b");
linked.put("a", "d");
System.out.println(linked);//有序的集合
}
}
集合的遍历
Map<K,V> :在map接口中有一个内部的接口Entry
当Map集合一创建,那么就会在Map集合中创建一个entry对象,用来记录键与值
(键值对对象,键与值的映射关系)–>结婚证
entrySet:把map集合内部的多个Entry对象取出来存储到一个set集合中
Set<Map.Entry<K,V>>
遍历set集合获取Set集合中每一个Entry对象
entry对象中的方法getKey()获取key
getValue()获取值
Map集合遍历的第二种方式
使用entry进行遍历
Map集合中的方法:
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的Set视图
实现步骤:
使用Map集合的方法entrySet(),把Map集合中多个entry对象取出来,存储到一个Set集合中
遍历Set集合,获取每一个Entry对象
使用Entry对象中的方法getKey()和getValue()获取键与值
把对象对应的值一个一个取出来。
================================
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
* Map集合的第一中遍历,键找值
* Set<K> keySet() 返回此映射中包含的键的Set的值
* keySet遍历map集合:
* 把key键取出来存储到一个set集合之中,遍历set集合,获取map集合中的每一个key
* 然后通过这个Map集合get(key)得到key,遍历map集合
*
*/
public class MapKeySet {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("杨颖", 165);
map.put("范冰冰", 170);
//返回一个set集合
Set<String> set = map.keySet();
//使用迭代器遍历Set集合,使用迭代器,要hasNext().
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
//通过Map集合中的方法get(key),通过key找到value
Integer value = map.get(key);
System.out.println(value);
}
System.out.println("--------------------");
//增强for
for (String key : set) {
Integer value = map.get(key);
System.out.println(key+"--"+value);
}
System.out.println("--------------------");
//增强for,一步完成。map.keySet()省略了set这一步,直接完成这个操作。
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key+"--"+value);
}
}
}
-----------------------------------------------------------------
public class MapEntrySet {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖", 168);
map.put("杨颖", 167);
map.put("范冰冰", 170);
//使用Map集合中的方法entrySet(),把Map集合中的多个Entry对象取出来村村到一个Set集合中
// Set<Map.Entry<String, Integer>> set = map.entrySet();
//使用这个方法返回的就是一个Set集合,这个集合中的内容包含一个Entry<String, Integer>
Set<Entry<String, Integer>> set = map.entrySet();
//遍历set集合获取每一个entry对象
//使用迭代器遍历集合
// Iterator<Entry<String, Integer>> it = set.iterator();
//使用迭代器,返回的就是一个对应的对象。
Iterator<Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Entry<String, Integer> entry = it.next();
//使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"--"+value);
}
//增强for,获取map集合中的键值对对象。
System.out.println("--------------------------");
for (Entry<String, Integer> entry : set) {
//使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"--"+value);
}
//直接fore可以打出来。
// for (Entry<String, Integer> entry : set) {
//
// }
}
}
==================================
/*
* 自定义的Person类型
*
*/
public class Person {
private String name ;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
//重写比较的方法。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
------------------------------------------------------------
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/*
* HashMap存储自定义类型键值
* Map集合保证key是唯一的
* 作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一
* 快捷键生成:
* 自定义类型中一定要重写hashCode方法和equals方法,来保证key的唯一性
*
*/
public class HashMapSavePerson {
public static void main(String[] args) {
// show01();
show02();
}
/*
* HashMap存续自定义类型键值
* key:String 类型
* value:Person类型
*/
private static void show01(){
//创建HashMap集合
HashMap<String,Person> map = new HashMap<>();
//添加元素
map.put("北京", new Person("张三",18));
map.put("上海", new Person("李四",20));
map.put("广州", new Person("王五",18));
map.put("北京", new Person("赵六",18));
//发现key已经重复了,下面的会替换掉上面的
//遍历集合,首先把这个map集合转换为set集合进行遍历。
Set<String> set = map.keySet();
for (String key : set) {
Person value = map.get(key);
System.out.println(key+"-->"+value);
}
}
/*
* 存储自定义类型
* key:Person类型
* Person类就必须重写hashCode方法和equals方法保证key唯一
* value:String类型
* 可以重复
*
*/
private static void show02(){
//创建
HashMap<Person,String> map = new HashMap<>();
//添加元素
map.put(new Person("张三",18), "英国");
map.put(new Person("秦始皇",28), "秦国");
map.put(new Person("普京",58), "俄罗斯");
map.put(new Person("张三",18), "毛里求斯");
//遍历
Set<Entry<Person, String>> set = map.entrySet();
for (Entry<Person, String> entry : set) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-->"+value);
}
}
}
import java.util.List;
import java.util.Map;
import java.util.Set;
/*
* JDK9的新特性
* List接口,Set接口,Map接口里面增加了一个静态方法of,可以向集合一次性的添加多个元素
* static <E> List <E> of (E.... elements)
* 当集合中存储的个数不在改变已经确定了,不再改变时使用
* of只适用于List接口Set接口,Map接口 不使用接口的实现类
* 一旦进行中这种方式的使用,表示不能进行其他的添加操作。
* 返回值是一个不能改变的量,集合不能在使用add,put方法添加元素,会抛出异常
* 注意事项:
* Set接口和Map接口在调用of方法的时候不能有重复的元素,否则会抛出异常
*
*
*/
public class DemoJdk9 {
public static void main(String[] args) {
//元素的个数已经确定的时候使用。
List<String> list = List.of("a","b","a","c");
//这样写类似数组,不能再添加了list.add不能添加,会抛异常
Set<String> set = Set.of("a","b","a","d");//非法参数异常,不能存储重复元素,也不支持操作
Map<String,Integer> map = Map.of("张三",18,"李四",19,"王五",20);
}
}
=================================
HashTable
java.util.HashTable<K,V>集合 implements Map<K,V>接口
HashTable:
最早期的单线程双列集合
底层也是一个哈希表
不能存储空值空键
和vector 在1.2版本之后被(HashMap)取代了,但是hashTable的子类Properties依然活跃
Properties:是唯一和IO结合的集合
HashMap可以存储null值和null键,底层是哈希表,是一个线程不安全的集合,多线程
=============================
import java.util.HashMap;
import java.util.Hashtable;
public class HashTableCls {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put(null, "a");
map.put("b", null);
map.put(null, null);
System.out.println(map);
System.out.println("-----------------------------------------");
//hashTable不能存储空值空键
Hashtable<String, String> table = new Hashtable<>();
table.put(null, "a");//空指针异常
table.put("b", null);//空指针异常
table.put(null, null);//空指针异常
}
}
Debug
/*
* Debug调试程序:
* 可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
* 双击行号,添加断点(每个方的第一行,哪里有bug添加到哪里)
* 选择debug执行程序,程序停留在添加的断点处,f8逐行执行车程序,
* f7进入到方法中,shift+f8跳出方法
* f9:跳到下一个断点,没有,就结束程序
* ctrl+f2退出debug模式
*
*/
public class DemoDebug {
public static void main(String[] args) {
int a = 10;
int b = 20;
int sum = a + b;
System.out.println(sum);
}
}
=============================================
练习
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/*
* 斗地主:有序
* jdk9
*
*
*/
public class DouDiZhuTest {
public static void main(String[] args) {
//准备
//创建一个map集合,存储牌的索引和组装io90好的牌
HashMap<Integer,String> poker = new HashMap<>();
//创建一个List集合,存储牌的索引
ArrayList<Integer> pokerIndex = new ArrayList<>();
//定义两个集合,存储花色和牌的序号
List<String> colors = List.of("红桃","方片","梅花","黑桃");
List<String> numbers = List.of("2","A","K","Q","J","10","9","8","7","6","5","4","3");
//把大王和小王添加到集合中
//定义牌的索引,第0号元素已经被认为是大王
int index = 0;
poker.put(index, "大王");
pokerIndex.add(index);
//这里是一号元素,一号元素被添加的HashMap中认定是小王。
index++;
poker.put(index, "小王");
pokerIndex.add(index);
index++;
//循环嵌套遍历两个集合,组装52张牌,存到集合当中
for(String number:numbers){
for(String color:colors){
//索引加字符串拼接成为行的牌
poker.put(index, color+number);
//下标索引自增,每添加一张牌索引增长添加的索引集合中。
pokerIndex.add(index);
index++;
}
}
System.out.println(poker);
System.out.println(pokerIndex);
//洗牌 shuffle
Collections.shuffle(pokerIndex);
System.out.println(pokerIndex);
//发牌
//定义四个集合,存储玩家牌的索引和底牌的索引
ArrayList<Integer> play01 = new ArrayList<>();
ArrayList<Integer> play02 = new ArrayList<>();
ArrayList<Integer> play03 = new ArrayList<>();
ArrayList<Integer> dipai = new ArrayList<>();
//遍历村存储索引的List集合,获取每一个牌的索引,list集合的大小是Size
for(int i = 0; i<pokerIndex.size();i++){
Integer in = pokerIndex.get(i);
//先判断底牌
if(i>=51){
//底牌
dipai.add(in);
}else if(i%3==0){
play01.add(in);
}else if(i%3==1){
play02.add(in);
}else if(i%3==2){
play03.add(in);
}
}
//排序
Collections.sort(play01);
Collections.sort(play02);
Collections.sort(play03);
Collections.sort(dipai);
//看牌调方法
lookPoker("刘德华", poker,play01);
lookPoker("周星驰", poker,play02);
lookPoker("周润发", poker,play03);
lookPoker("底牌", poker,dipai);
}
//看牌
//需要遍历这四个集合,定义一个方法,提高代码的复用性
public static void lookPoker(String name,HashMap<Integer,String> poker, ArrayList<Integer> list){
for (Integer key : list) {
String value = poker.get(key);
System.out.println(value+" ");
}
System.out.println();//打印完每一个玩家的牌换行
}
}
------------------------------------------
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
/*
* 练习:
* 计算一个字符串中每个字符创出现的次数
* 分析;使用Scanner获取用户输入的字符串
* 创建Map集合key是字符串的字符,value是字符的个数
* 遍历字符串,获取每一个字符
* 这种获取,字符串需要转换为字符数组,遍历这个字符数组
* 使用获取到的字符,去Map集合判断key是否存在
* key存在:
* 通过字符(key) 获取value(字符个数)
* value++
* put(key, value) 把新的value 存储到map集合中
* key不存在
* map.put(key,1);
* 遍历map集合,输出结果
*
*
*/
public class MapTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//创建集合
HashMap<Character,Integer> map = new HashMap<>();
//遍历字符串,获取每一个字符, 这种获取,字符串需要转换为字符数组,遍历这个字符数组
for(char c:str.toCharArray()){
System.out.println("元素是"+c);
//判断,不用输出征数组,直接进行map集合的判断即可。
if(map.containsKey(c)){
Integer value = map.get(c);
value++;
//存储
map.put(c, value);
}else{
//key不存在
map.put(c, 1);
}
}
//遍历输出
for(Character key:map.keySet()){
Integer value = map.get(key);
System.out.println(key+"-->"+value);
}
}
}