title: 双列集合
index_img: img/21.svg
tags:
- Java SE
- 集合
categories:
- Java SE
hide: false
excerpt: 原理、常用方法、遍历
双列集合
由一对对元素组成{key-value}
的集合。
- 一次存一对数据
key
不能重复【元素对唯一】,value
可以- key和value是一一映射关系
{key-value}
称为键值对(对象),再java中叫做Entry
对象
双列集合接口Map
常用方法
方法名称 | 说明 |
---|---|
V put(K key, V value) | 添加元素(元素存在【看key】就会覆盖) |
V remove(Object key) | 根据键删除键值对元素,返回value或null |
clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
size() | 集合的长度,也就是集合中键值对的个数 |
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("张三", 12); //添加和覆盖数据
map.put("李斯", 23);
map.put("李斯", 32); //key相同覆盖前一个
map.put("Tom", 12);
System.out.println(map);
System.out.println("--------------");
if (map.containsKey("张三")) {
map.remove("张三");
}
System.out.println(map);
System.out.println("--------------");
if (map.isEmpty()) {
System.out.println("map空");
} else {
System.out.println(map.size());
}
}
}
遍历
键找值
- 键是唯一的,可以根据键找值
- 将键放入单列集合,然后遍历【单列集合】
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("Tom", 100);
map.put("Lay", 90);
map.put("kup", 90);
map.put("duk", 0);
Set<String> keys = map.keySet(); //将键放在单列集合中
//forEach
keys.forEach(s -> {
System.out.println("{" + s + "-" + map.get(s) + "}"); //通过map集合的get(key)获取Value
});
//增强for
System.out.println("-------------");
for (String s : keys) {
System.out.println("{" + s + "-" + map.get(s) + "}");
}
//迭代器
System.out.println("-------------");
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println("{" + s + "-" + map.get(s) + "}");
}
}
}
键值对
获取键值对对象,放入单列集合,遍历【单列集合】
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("Tom", 100);
map.put("Lay", 90);
map.put("kup", 90);
map.put("duk", 0);
Set<Map.Entry<String, Integer>> entries = map.entrySet(); //Entry是Map中定义的一个接口,用于管理键值对set对象
entries.forEach(s -> System.out.println("{" + s.getKey() + "-" + s.getValue() + "}"));
System.out.println("------------------");
for (Map.Entry<String, Integer> s : entries) {
System.out.println("{" + s.getKey() + "-" + s.getValue() + "}");
}
System.out.println("----------------");
Iterator<Map.Entry<String, Integer>> it = entries.iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> s = it.next();
System.out.println("{" + s.getKey() + "-" + s.getValue() + "}");
}
}
}
forEach遍历Map
- 这里底层使用的是键值对方式
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("李白", "天生我材必有用");
map.put("杜甫", "国破山河在");
map.put("李清照", "不肯过江东");
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
System.out.println("{" + key + "-" + value + "}");
}
});
System.out.println("------------------");
map.forEach((key, value) -> System.out.println("{" + key + "-" + value + "}"));
}
}
双列集合实现类
HashMap
- 无序、不重复【key决定的】、无索引
- 底层结构与HashSet一样(数组、链表、红黑树),但规则有些不同
- 使用的只是
Key
的哈希值【自定义对象只需要重写key的hashCode和equals即可】 - 哈希值一样,是直接覆盖,而不是丢弃不存
- 哈希值不一样是与HashSet一样
- 当HashMap中的元素数量超过了负载因子(默认为0.75)与当前容量的乘积时,HashMap就会进行扩容。扩容后的容量是原来的两倍【新建数组】。
- 使用的只是
如此:
通过重写equals
和hashCode
来保证Key的唯一性
- 如果键是自定义对象【如学生】需要两个方法都重写【非自定义对象,java写好了】
- 如果值是自定义对象,都不需要重写
问题描述
创建一个HashMap集合,键【重写】是学生对象(Student),值是籍贯(String)。
- 存储三个键值对元素,并遍历
- 要求:同姓名,同年龄认为是同一个学生【重写】
- 可以通过的新学生对象否覆盖来判断
public class Main {
public static void main(String[] args) {
HashMap<Student, String> stu = new HashMap<>();
Student stu1 = new Student("张三", 18);
Student stu2 = new Student("李四", 8);
Student stu3 = new Student("王五", 12);
Student stu4 = new Student("王五", 12);
stu.put(stu1, "云南");
stu.put(stu2, "江苏");
stu.put(stu3, "浙江");
stu.put(stu4, "黑龙江"); //重写则覆盖stu3【已经重写】,否则会由两个王五,不符合要求
//键找值遍历
Set<Student> set = stu.keySet();
set.forEach(s -> System.out.println("{" + s + "-" + stu.get(s) + "}"));
System.out.println("---------");
//键值对遍历
for (Map.Entry<Student, String> s : stu.entrySet()) {
System.out.println("{" + s.getKey() + "-" + s.getValue() + "}");
}
System.out.println("---------");
//map的forEach
stu.forEach((key, value) -> System.out.println("{" + key + "-" + value + "}"));
}
}
某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。
- 可以定义为map集合
- 判断收集到的数据中,key是否存在
- 存在,数目+1,覆盖
- 不存在,新建
public class Main {
public static void main(String[] args) {
//投票的数据
String[] arr = {"A", "B", "C", "D"}; //存储键,也可以使用单列集合
//模拟投票和存储
Random random = new Random();
ArrayList<String> list = new ArrayList<>();//存储80个投票的结果【ABCD之间】
for (int i = 0; i < 80; i++) {
int index = random.nextInt(arr.length); //再【0~4)之间生成数字,模拟投票的选择在ABCD之间
list.add(arr[index]);
}
//统计规则:使用map适应性比计数器更好
HashMap<String, Integer> map = new HashMap<>();
for (String key : list) {
if (map.containsKey(key)) {
//当前key存在,获取先前票数【Value】,然后++,然后覆盖
int count = map.get(key);
count++;
map.put(key, count);
} else {
//当前key不存在
map.put(key, 1);
}
}
//打印统计信息
System.out.println(map);
//统计投票信息,求最大值(可能由多个)
int max = 0; //以0为基准
for (Map.Entry<String, Integer> kv : map.entrySet()) {
int num = kv.getValue();
if (num > max) {
max = num;
}
}
System.out.println("max:" + max);
//如果由多个最大值,需要都打出
for (Map.Entry<String, Integer> skv : map.entrySet()) {
int num = skv.getValue();
if (num == max) {
System.out.println("max:" + num);
}
}
}
}
LinkedHashMap
- 有序、不重复【key】、无索引
- 存取有序
- 底层结构,哈希表+双链表存储存取顺序
public class Main {
public static void main(String[] args) {
LinkedHashMap<String, String> linkMap = new LinkedHashMap<>();
linkMap.put("C", "1");
linkMap.put("D", "2");
linkMap.put("A", "3");
linkMap.put("F", "4");
linkMap.forEach((key, value) -> System.out.println("{" + key + "-" + value + "}")); //有序
}
}
TreeMap
TreeMap跟TreeSet底层原理一样,都是红黑树结构的。
由键决定特性:不重复、无索引、可排序【键排序】
自定义排序依旧可以使用两种方法(参考TreeSet)
问题描述
键:整数表示id
值:字符串表示商品名称
要求:按照id的升序排列
方法1:javabean实现Compareable
接口
public class Goods implements Comparable<Goods> {
@Override
public int compareTo(Goods goods) {
return this.ID - goods.ID;
}
重写hashCode和equals
...
public class Main {
public static void main(String[] args) {
Goods goods1 = new Goods("小吃1", 5);
Goods goods2 = new Goods("小吃2", 3);
Goods goods3 = new Goods("小吃3", 4);
Goods goods4 = new Goods("小吃4", 1);
TreeMap<Goods, String> treeMap = new TreeMap<>();
treeMap.put(goods1, "小吃区");
treeMap.put(goods2, "小吃区");
treeMap.put(goods3, "小吃区");
treeMap.put(goods4, "小吃区");
treeMap.forEach((key, value) -> System.out.println("[" + key + "-" + value + "]"));
}
}
方法2:javabean实现Comparator
接口
- 这里我们用降序来区分
public class Main {
public static void main(String[] args) {
Goods goods1 = new Goods("小吃1", 5);
Goods goods2 = new Goods("小吃2", 3);
Goods goods3 = new Goods("小吃3", 4);
Goods goods4 = new Goods("小吃4", 1);
TreeMap<Goods, String> treeMap = new TreeMap<>((s1,s2)->Integer.compare(s2.ID,s1.ID)); //注意
treeMap.put(goods1, "小吃区");
treeMap.put(goods2, "小吃区");
treeMap.put(goods3, "小吃区");
treeMap.put(goods4, "小吃区");
treeMap.forEach((key, value) -> System.out.println("[" + key + "-" + value + "]"));
}
}
标签:map,put,System,双列,key,集合,println,out
From: https://www.cnblogs.com/SimpleWord/p/17689191.html