一個 key 能儲存多個 value 的 map --- 自定義的 MultiValueMap,實現 Map 介面
需要實現一個 key 能儲存多個 value 的 map,一個鍵可以對應多個值。
這樣多儲存一些 key 對應的 value,方便業務中使用。
比如,儲存使用者每個小時內登陸的次數,用這樣的 map ,就比在 HashMap 的 value 裡存 時間和登陸次數 拼接的字串更方便。
需要的效果是:
user1 [2019-03-09 22:00:00, 10次]
user2 [2019-03-09 22:00:00, 8次]
上網搜“一個 key 儲存多個 value 的 map”,發現有的部落格裡說可以用 IdentityHashMap。
可是我試了一下,發現沒實現我要的功能。
繼續搜,找到一種解決方法:https://www.cnblogs.com/jiadp/p/9335437.html
這篇部落格裡,作者將 LinkedHashMap 的 value 替換成 List<Object> 來實現這樣的功能。
只不過這篇部落格裡的 LinkedMultiValueMap 實現的是 interface MultiValueMap 這樣的介面,用起來稍微有些不方便。
我在這篇部落格的基礎上做了一些修改,讓它實現了常見的 Map 介面,用起來更方便一些。
我修改後程式碼如下:
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
/** 一個 Key 儲存多個 Value 的 Map,一個鍵可以對應多個值
* 將 LinkedHashMap 的 value 替換成 List<Object> 來實現這樣的功能
*/
public class MultiValueMap<K, V> implements Map<String, Object>{
//
private Map<String, List<Object>> sourceMap =
new LinkedHashMap<String, List<Object>>();
public MultiValueMap(){}
//
public void put(String key, List<Object> values){
// 遍歷新增進來的 List 的 Value,呼叫上面的 put(K, V) 方法新增
for(Object value : values){
put(key, value);
}
}
//
public void set(String key, Object value){
// 移除這個 Key,新增新的 Key-Value
sourceMap.remove(key);
put(key, value);
}
//
public void set(String key, List<Object> values){
// 移除 Key,新增 List<V>
sourceMap.remove(key);
put(key, values);
}
//
public void set(Map<String, List<Object>> map){
// 移除所有值,遍歷 Map 裡的所有值新增進來
sourceMap.clear();
sourceMap.putAll(map);
}
//
public void clear(){
sourceMap.clear();
}
//
public Set<String> keySet(){
return sourceMap.keySet();
}
//
public List<Object> values(){
// 建立一個臨時 List 儲存所有的 Value
List<Object> allValues = new ArrayList<>();
// 遍歷所有的Key的Value新增到臨時List
Set<String> keySet = sourceMap.keySet();
for(Object key : keySet){
allValues.addAll(sourceMap.get(key));
}
return allValues;
}
//
public List<Object> getValues(Object key){
return sourceMap.get(key);
}
//
public Object getValue(String key, int index){
List<Object> values = sourceMap.get(key);
if(values != null && index < values.size()){
return values.get(index);
}
return null;
}
//
public int size(){
return sourceMap.size();
}
//
public boolean isEmpty(){
return sourceMap.isEmpty();
}
//
public boolean containsKey(Object key){
return sourceMap.containsKey(key);
}
//
public Object put(String key, Object value){
if(key != null){
// 如果沒有就建立一個 List 並新增 Value
if(!sourceMap.containsKey(key)){
List<Object> list = new ArrayList<Object>();
sourceMap.put(key, list);
}
boolean re = sourceMap.get(key).add(value);
return re;
}else{
return false;
}
}
//
public Object get(Object key){
return sourceMap.get(key);
}
//
public Object remove(Object key){
return sourceMap.remove(key);
}
//
public void putAll(Map map){
for(Object entry : map.entrySet()){
Map.Entry<String, Object> en = (Map.Entry<String, Object>) entry;
String key = en.getKey();
Object value = en.getValue();
if(value instanceof List){
List<Object> values = (List<Object>) value;
put(key, values);
}else{
put(key, value);
}
}
}
//
public boolean containsValue(Object value){
List<Object> values = values();
if(value instanceof List){
List<Object> aList = (List<Object>) value;
// Returns true if this list contains all of the elements of the specified collection.
return values.containsAll(aList);
}else{
return values.contains(value);
}
}
//
public Set entrySet(){
return sourceMap.entrySet();
}
// ------------------------ 測試這個類 ------------------------------
/** 獲得當前日期的字串,格式 yyyy-MM-dd HH:00:00 */
public static String getStringTimeToHour(){
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:00:00");
return fmt.format(new Date());
}
/** 生成一個隨機整數,範圍從 1 到 10 */
public static int getRandomIntRangeFrom1To10(){
int random = new Random().nextInt(10) + 1;
return random;
}
// main
public static void main(String[] a){
String id1 = 123 + "";
String id2 = 124 + "";
String id3 = 125 + "";
String id4 = 126 + "";
Map<String, Object> map6 = new MultiValueMap<>();
// 測試 put
map6.put(id1, "Wade");
map6.put(id1, getStringTimeToHour());
map6.put(id1, getRandomIntRangeFrom1To10());
map6.put(id2, "Ibrahimovic");
map6.put(id2, getStringTimeToHour());
map6.put(id2, getRandomIntRangeFrom1To10());
map6.put(id3, "Dejokovic" );
map6.put(id3, getStringTimeToHour());
map6.put(id3, getRandomIntRangeFrom1To10());
map6.put(id4, "Van Persie");
map6.put(id4, getStringTimeToHour());
map6.put(id4, getRandomIntRangeFrom1To10());
// 測試 keySet。用 keySet 遍歷,並列印
for(String key : map6.keySet()){
List<Object> values = (List<Object>) map6.get(key);
for(Object value : values){
System.out.println(key + ": " + value);
}
System.out.println();
}
// 測試 putAll
Map<String, Object> map = new HashMap<>();
List<Object> valuesF = new ArrayList<>();
String idF = "127";
//map.put(idF, "Figo");
//map6.putAll(map);
valuesF.add("Figo");
valuesF.add(getStringTimeToHour());
valuesF.add(getRandomIntRangeFrom1To10());
map.put(idF, valuesF);
map6.putAll(map);
// 測試 containsValue
System.out.println( map6.containsValue("Figo"));
System.out.println( map6.containsValue(valuesF));
System.out.println();
// 測試 entrySet。用 entrySet 遍歷,並列印
for(Object entry : map6.entrySet()){
Map.Entry<String, Object> en = (Map.Entry<String, Object>) entry;
String key = en.getKey();
Object value = en.getValue();
System.out.println(key + " " + value.toString());
}
System.out.println();
// 測試 get
System.out.println( map6.get( "127" ) );
}
}
列印結果:
123: Wade
123: 2019-03-09 22:00:00
123: 10
124: Ibrahimovic
124: 2019-03-09 22:00:00
124: 8
125: Dejokovic
125: 2019-03-09 22:00:00
125: 8
126: Van Persie
126: 2019-03-09 22:00:00
126: 6
true
true
123 [Wade, 2019-03-09 22:00:00, 10]
124 [Ibrahimovic, 2019-03-09 22:00:00, 8]
125 [Dejokovic, 2019-03-09 22:00:00, 8]
126 [Van Persie, 2019-03-09 22:00:00, 6]
127 [Figo, 2019-03-09 22:00:00, 9]
[Figo, 2019-03-09 22:00:00, 9]
------------------------------------------------
如果這樣新增:
String id211 = "212";
List<Object> values2a = new ArrayList<>();
values2a.add( "2019-3-1 01:00:00" );
values2a.add( getRandomIntRangeFrom1To10() );
map6.put( id211, values2a );
List<Object> values2b = new ArrayList<>();
values2b.add( "2019-3-1 02:00:00" );
values2b.add( getRandomIntRangeFrom1To10() );
map6.put( id211, values2b );
列印結果就是: 212 [[2019-3-1 01:00:00, 8], [2019-3-1 02:00:00, 3]]
可以起到儲存時間段和登陸次數的作用。
相關文章
- Spring-MultiValueMap(一個Key對應多個Value)Spring
- mybatis中查詢出多個以key,value的屬性記錄,封裝成一個map返回的方法MyBatis封裝
- Java交換map的key和value值Java
- 判斷Map集合中是否存在某一個key
- Golang自定義結構體轉map 第二個人的思路Golang結構體
- Java中將多個Map扁平化為單個MapJava
- 自定義限速功能實踐——Map 版本
- Java : List中 根據map的某個key去重Java
- 根據key集合批次從map中獲取value
- java8 實現map以value值排序Java排序
- Flutter持久化儲存之key-value儲存Flutter持久化
- Java中將 Map 轉換為 Spring MultiValueMapJavaSpring
- List<實體類>轉換成map 一個鍵對應多個值
- 儲存過程定義多個遊標多個begin儲存過程
- 一個map函式引發的血案函式
- 一個高效能的go 紅黑樹 map, 模擬STL實現Go
- 用struct做unordered_map的keyStruct
- Golang Map實現(四) map 的賦值和擴容Golang賦值
- std::map 自定義key型別,重寫operator<() 沒有嚴格弱序引起的“invalid comparator”型別
- 一個介面優雅的實現 Spring Cloud OAuth2 自定義token返回格式SpringCloudOAuth
- 踩了 Golang sync.Map 的一個坑Golang
- 解碼 xsync 的 map 實現
- GO 中 map 的實現原理Go
- 一個小巧而強大的 Key-Value 管理框架框架
- LightKV-高效能key-value儲存元件元件
- java8的stream將一個List轉為按照某個欄位分組的map,再按照另一個欄位取max最終得到一個mapJava
- 如何動手實現一個自定義的通訊協議?協議
- SpringSession系列-儲存機制之Redis&MapSpringGseSessionRedis
- 給請求追加自定義值 $request->offsetSet ($key,$value)
- JAVA集合——Map介面Java
- Oracle儲存過程中定義多個遊標Oracle儲存過程
- 一個工具類實現自定義Tablayout的下劃線寬度TabLayout
- map自定義排序,根據鍵或者值排隊排序
- 使用SpringBoot JPA進行自定義的儲存及批量儲存Spring Boot
- Map類及其主要的實現類
- Go語言map的底層實現Go
- 深入 Go 的 Map 使用和實現原理Go
- hadoop透過CombineFileInputFormat實現小檔案合併減少map的個數HadoopORM