Java(一百五十四)Map

45 阅读9分钟

之前有一个想法做一个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<StringObject> 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<StringObjectresult = 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<StringObjectresult = 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<StringObjectresult = 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<StringObjecttest()
 {
     Map<StringObject> 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<StringObjecttest()
 {
     Map<StringObject> 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,Objectitem: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<StringObjectresult = new HashMap<>(10);
     result.put("c"1);
     result.put("b"3);
     result.put("a"2);
 
     // 将HashMap转换为List<Entry>类型
     List<Map.Entry<StringObject>> 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<StringObjecttest() {
         Map<StringObject> result = new TreeMap<>();
         result.put("a"3);
         result.put("c"2);
         result.put("b"1);
         Object firstKey = ((TreeMap<StringObject>) result).firstKey();
         Object lastKey = ((TreeMap<StringObject>) 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<StringString> 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<StringObjectmap = 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<StringObject> test() {
         Map<StringObject> map = new LinkedHashMap<>();
         map.put("d""ccccc");
         map.put("b""aaaaa");
         map.put("a""ddddd");
         map.put("c""bbbbb");
 
         Iterator<Stringiterator = 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的基本使用。

 

有好的建议,请在下方输入你的评论。