一个 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]]

可以起到保存时间段和登陆次数的作用。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值