之前有一个想法做一个SpringBoot的项目,将博客的后端从PHP的laravel框架改成java的SpringBoot框架,也算是对过去这一段时间java学习成果的一个小检验
在做项目的时候,发现一个小问题:PHP是没有类型这一说的,所以他的一个数组可以装下所有的数据,但是java不行。现在的情况是,我的接口返回值中既有int类型,也有list类型的数据。我应该怎么将他们放入一个对象中返回给前端呢?
我得承认,从弱语法类型的语言转到强语法类型的语言,脑子多少是有点不够用。
我第一个想到的方法是,我定义一个实体类,把我需要的返回参数定义成类的属性,我实例化一个类对象,再将我想要返回到前端的数据赋值到类对象中。再返回给前端,这样问题不就解决了嘛。
但是有一个小小的问题,难道我每一个接口返回的参数都需要定义一个实体类么?这显然是不合理的。我寻思还是百度一下吧,得到的最多的结果是使用map。
我翻找我之前的学习笔记,我的天,map这个玩意我竟然没有学习到。既然如此,那我就在这里补充一下java的map
一:什么是map
Map是键值对的集合接口,称之为映射,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。
简单讲这个玩意我直接那他当PHP里边的数组使用
PHP的写法:
$result = [];
$result['code'] = 1;
$result['msg'] = '操作成功';
$result['articleShow'] = $articleShow;
return $result;
java使用hashmap实现上方的写法:
// 定义返回值
Map<String, Object> result = new HashMap<>(4);
result.put("dataDatanum", articleNum);
result.put("articleShow", articleList);
result.put("code", 1);
result.put("articlePage", articlePage);
return result;
完美,上方的代码就是目前我对map的使用。
二:Hashmap
基于哈希表实现,具有快速的查找和插入操作,适用于需要快速查找键值对的场景。允许多条记录的Value为 Null。非同步的。
1 : Hashmap 具有以下方法:
put(K key, V value): 将指定的键值对添加到HashMap中。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
return result;
}
页面输出:
{
"a": 1111,
"b": 333,
"code": 5,
"c": "aaaaa"
}
map的键不能重复,重复会覆盖。
remove(Object key): 从HashMap中移除指定键的键值对。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
result.remove("a");
return result;
}
页面输出:
{
"b": 333,
"code": 5,
"c": "aaaaa"
}
get(Object key): 返回指定键对应的值。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
result.remove("a");
Object str = result.get("code");
System.out.println(str);
return result;
}
运行代码,控制台输出:
5
containsKey(Object key): 检查HashMap中是否包含指定的键。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
result.remove("a");
Object str = result.get("code");
System.out.println(str);
Boolean bool = result.containsKey("code");
System.out.println(bool);
Boolean bool2 = result.containsKey("d");
System.out.println(bool2);
return result;
}
控制台输出:
5
true
false
containsValue(Object value): 检查HashMap中是否包含指定的值。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
result.remove("a");
Object str = result.get("code");
System.out.println(str);
Boolean bool = result.containsKey("code");
System.out.println(bool);
Boolean bool2 = result.containsKey("d");
System.out.println(bool2);
Boolean bool3 = result.containsValue(5);
System.out.println(bool3);
Boolean bool4 = result.containsValue(222222);
System.out.println(bool4);
return result;
}
控制台输出:
5
true
false
true
false
size(): 返回HashMap中键值对的数量。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
result.remove("a");
Object str = result.get("code");
System.out.println(str);
Boolean bool = result.containsKey("code");
System.out.println(bool);
Boolean bool2 = result.containsKey("d");
System.out.println(bool2);
Boolean bool3 = result.containsValue(5);
System.out.println(bool3);
Boolean bool4 = result.containsValue(222222);
System.out.println(bool4);
int num = result.size();
System.out.println(num);
return result;
}
控制台输出:
5
true
false
true
false
3
2:循环
废话不多说,直接上代码,使用增强for循环。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
{
Map<String, Object> result = new HashMap<>(10);
result.put("code", 2);
result.put("code", 5);
result.put("a", 1111);
result.put("b", 333);
result.put("c","aaaaa");
List<Map.Entry<String,Object>> list = new ArrayList<Map.Entry<String,Object>>(result.entrySet());
for(Map.Entry<String,Object> item:list)
{
System.out.println(item.getKey()+":"+item.getValue());
}
return result;
}
运行代码,控制台输出:
a:1111
b:333
code:5
c:aaaaa
上方的代码是先将map转换成一个list,然后再使用增强for循环来遍历list,用到了map的一个方法:
entrySet():返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
3:排序
通过上方for循环输出的内容,我们可以发现HashMap的值是没有顺序的,他是按照key的HashCode来实现的,对于这个无序的HashMap我们需要使用比较器:Comparator。
Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数。如下:
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test() {
Map<String, Object> result = new HashMap<>(10);
result.put("c", 1);
result.put("b", 3);
result.put("a", 2);
// 将HashMap转换为List<Entry>类型
List<Map.Entry<String, Object>> list = new ArrayList<>(result.entrySet());
// 按照值value升序排序(我的map中的value是object类型,没有办法使用compareTo方法,只能使用object中的toString方法比较)
Collections.sort(list, Comparator.comparing(o -> o.getValue().toString()));
//按照键值升序排序(我的map中的value是object类型,没有办法使用compareTo方法,只能使用object中的qequals方法比较)
//Collections.sort(list, (o1, o2) -> o1.getValue().equals(o2.getValue()) ? 0 : (o1.getValue().toString().length() - o2.getValue().toString().length()));for(Map.Entry<String,Object> item:list)
for (Map.Entry<String, Object> item : list) {
System.out.println(item.getKey() + ":" + item.getValue());
}
return result;
}
控制台输出:
a:2
b:3
c:1
注意上方代码中的注释,我这里提供了两种排序方式,一种是按键值key排序,另一种是按照value值排序。自己尝试一下即可。
三:TreeMap
TreeMap是Map接口的另一个常见实现类,它基于红黑树实现,可以对键进行排序,并提供了一系列与排序相关的方法。
默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
1:常用treemap方法:
put(K key, V value): 将指定的键值对添加到TreeMap中。
remove(Object key): 从TreeMap中移除指定键的键值对。
get(Object key): 返回指定键对应的值。
containsKey(Object key): 检查TreeMap中是否包含指定的键。
size(): 返回TreeMap中键值对的数量。
firstKey(): 返回TreeMap中的第一个键。
lastKey(): 返回TreeMap中的最后一个键。
Hashmap中已经演示过的方法这里不再赘述。代码实例:
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test() {
Map<String, Object> result = new TreeMap<>();
result.put("a", 3);
result.put("c", 2);
result.put("b", 1);
Object firstKey = ((TreeMap<String, Object>) result).firstKey();
Object lastKey = ((TreeMap<String, Object>) result).lastKey();
System.out.println(firstKey);
System.out.println(lastKey);
return null;
}
运行代码,控制台输出:
a
c
2:排序 + 循环
(1):按键值key排序
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test()
Map<String, String> map = new TreeMap<>(
// 键值倒序
// Comparator.reverseOrder()
// 键值正序
Comparator.naturalOrder()
);
map.put("c", "ccccc");
map.put("a", "aaaaa");
map.put("b", "bbbbb");
map.put("d", "ddddd");
Set<String> keySet = map.keySet();
Iterator<String> iter = keySet.iterator();
while (iter.hasNext()) {
String key = iter.next();
System.out.println(key + ":" + map.get(key));
}
return null;
}
(2):按值value排序
对value排序我们就需要 借助于Collections的sort(List list, Comparator<? super T> c)方法,该方法根据指定比较器产生的顺序对指定列表进行排序。但是有一个前提条件,那就是所有的元素都必须能够根据所提供的比较器来进行比较。
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test() {
Map<String, Object> map = new TreeMap<>();
map.put("d", "ccccc");
map.put("b", "aaaaa");
map.put("a", "ddddd");
map.put("c", "bbbbb");
//这里将map.entrySet()转换成list
List<Map.Entry<String,Object>> list = new ArrayList<>(map.entrySet());
//然后通过比较器来实现排序
//升序排序
Collections.sort(list, Comparator.comparing(o -> o.getValue().toString()));
for(Map.Entry<String,Object> mapping:list)
{
System.out.println(mapping.getKey()+":"+mapping.getValue());
}
return null;
}
按值排序这个和hashmap中的用法是一样的。
四:LinkedHashMap
LinkedHashMap是Map接口的另一个实现类,它基于哈希表和链表实现,并保持键值对的插入顺序。在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的
1:常用的LinkedHashMap方法:(这部分使用方法参考hashmap)
put(K key, V value): 将指定的键值对添加到LinkedHashMap中。
remove(Object key): 从LinkedHashMap中移除指定键的键值对。
get(Object key): 返回指定键对应的值。
containsKey(Object key): 检查LinkedHashMap中是否包含指定的键。
size(): 返回LinkedHashMap中键值对的数量。
2:循环
在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.
@GetMapping("index/test")
@ResponseBody
public Map<String, Object> test() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("d", "ccccc");
map.put("b", "aaaaa");
map.put("a", "ddddd");
map.put("c", "bbbbb");
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
System.out.println(key + ":" + map.get(key));
}
return null;
}
运行代码,控制台输出:
d:ccccc
b:aaaaa
a:ddddd
c:bbbbb
五:Hashtable
与 HashMap类似,不同的是:key和value的值均不允许为null;
它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
六:Map的常用API
| clear() | 从 Map 中删除所有映射 |
|---|---|
| remove(Object key) | 从 Map 中删除键和关联的值 |
| put(Object key, Object value) | 将指定值与指定键相关联 |
| putAll(Map t) | 将指定 Map 中的所有映射复制到此 map |
| entrySet() | 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素 |
| keySet() | 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值) |
| values() | 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值) |
| get(Object key) | 返回与指定键关联的值 |
| containsKey(Object key) | 如果 Map 包含指定键的映射,则返回 true |
| containsValue(Object value) | 如果此 Map 将一个或多个键映射到指定值,则返回 true |
| isEmpty() | 如果 Map 不包含键-值映射,则返回 true |
| size() | 返回 Map 中的键-值映射的数目 |
七:Map和Collection集合的区别
1:Map集合的特点:
将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值
2:Map和Collection集合的区别:
1:Map集合存储元素是成对出现的,Map的键是唯一的,值是可以重复的
2:Col1ect1on集合存储元素是单独出现的,Collect1on的儿子Set是唯一的,List是可重复的
3:要点:
1:Map集合的数据结构针对键有效,跟值无关
2:Co11 ection集合的数据结构针对元素有效
以上大概就是java中map的基本使用。
有好的建议,请在下方输入你的评论。