map用法及对List<对象>分组成Map<String,List<对象>>的方案

Map中的集合,元素是成对存在的(理解为夫妻)。
每个元素由键与值两部分组成,通过键可以找对所对应的值
Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值
特点:键不重复,值可以重复--每个键只能对应一个
基础方法:
1. keyset      public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。
2. entrySet   public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。
3. public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
4. public V remove(Object key): 把指定的键所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
5. public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

    Map<String, String> map = new HashMap(); 
    map.put(test1, "张三上班"); 
    map.put(test2, "李四下班"); 

    //第一种  可以获取key和value
    Set<Map.Entry<String, String>> entryseSet=map.entrySet(); 
    for (Map.Entry<String, String> entry:entryseSet) {
         System.out.println("第一种:entry.getKey());
         System.out.println("第一种:entry.getValue());
    }
    
    //第二种 根据key找value
    Set<String> set = map.keySet(); //取出所有的key值
    for (String key:set) {
     	System.out.println("第二种:"+key); 
        System.out.println("第二种:"+map.get(key)); 
    }
    
    //第三种 根据key找value
    Iterator it = map.keySet().iterator();
    while(it.hasNext()){
       String value = map.get(it.next());
       System.out.println("第三种:"+key); 
       System.out.println("第三种:"+value);
    }

1.map原生没有add()方法,add()存在在list中,对象使用set()方法

map原生没有add()方法,如果需要,可以创建个util工具类调用,网上有资源

2.map只有put(),且根据key值重复会覆盖

private AlibabaRequest setRequest(msgRecordDto insertData, Long userId,List<msgRecordEntity> msgList, String phoneNumber) {
    AlibabaRequest AlibabaRequest = new AlibabaRequest();
    AlibabaRequest.setPhoneNums(phoneNumber);
    
    Map<String, String> paramsMap = Maps.newHashMap();
    // 将code插入到map
    paramsMap.put("code", RandomStringUtils.randomNumeric(6));
    
    //将map插入到AlibabaRequest对象的map字段中
    AlibabaRequest.setParamsMap(paramsMap);
    return AlibabaRequest;
}

 map的去重及序列化

private void sendBatchSms(msgRecordDto data, List<AlibabaRequest> requestList) {
    Map<String, Object> params = Maps.newHashMap();
    params.put("templateCode", data.getTemplateCode());
    //等价于distinctByKey,起到去重的作用,并添加序列化供统一调用
    params.put("requestList",JSON.toJSONString(requestList.stream()
   				.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> 
            	new TreeSet<AlibabaRequest>(Comparator.comparing(AlibabaRequest::getPhoneNums))),
            	ArrayList::new)), SerializerFeature.WriteClassName));
    NotifierMessage msg = new NotifierMessage();
    msg.setBusinessSn(UUID.randomUUID().toString());
    msg.setSystemCode(SystemCode.SYS_COD.getSysCode());
    //将params的map数据插入到msg的map字段中
    msg.setParams(params);
    rabbitProducer.handlerNotify(msg);
}

延时队列,延时队列+优先级队列=实现插队 

//延时队列,延时队列+优先级队列=实现插队
public Queue delayQueue() {
    Map<String, Object> args = new HashMap<>(2);
   
    args.put(RabbitConstants.DEAD_LETTER_EXCHANGE, RabbitConstants.SIS_DIRECT_EXCHANGE);
    args.put(RabbitConstants.DEAD_LETTER_ROUTING_KEY, RabbitConstants.ROUTING_KEY);
    
    return QueueBuilder.durable(RabbitConstants.QUEUE_DELAY).withArguments(args).build();
}

map是所有map的父类(基础类,也可以通过new构造对象),是多态的用法,相当于map是接口抽象类,而其他map是实现该接口的类
LinkedHashMap双向链表来保存节点的访问顺序,所以保证了有序性,HashMap 是无序的 

map是所有map的父类(基础类,也可以通过new构造对象),是多态的用法,相当于map是接口抽象类,而其他map是实现该接口的类
LinkedHashMap双向链表来保存节点的访问顺序,所以保证了有序性,HashMap 是无序的

Map<String,Object> map = new LinkedHashMap<>();
map.put("xrange", xrange);
map.put("yrange", yrange);
map.put("dataList", dataString);
calEndTime(map, startTime);
return map;

3.map衍生的子类

HashMap:
  1.存储数据采用的哈希表结构,元素的存取顺序不能保证一致。
  2.由于要保证键的唯一、不重复,如要使用hashCode()、equals()方法,需要重写。
  3.HashMap存储自定义类型键值,如果自定义对象作为key存在,必须保证对象唯一。


Hastable:
  1.HashMap则非线程安全,两者最主要的区别在于Hashtable是线程安全
  2.HashMap可以使用null作为key,而Hashtable则不允许null作为key
  3.HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类
  4.HashMap扩容时是当前容量为:capacity*2,Hashtable扩容时是容量为:capacity*2+1


LinkedHashMap:  
  1.初始化大小是16,可以根据数据量设置初始化大小
       2.最大的装载因子默认是0.75,当HashMap中元素个数达到容量的0.75时,就会扩容,容量为原来的两倍。 
       3.HashMap底层采用链表法来解决冲突。 但是如果链表过长会影响性能,JDK1.8对HashMap通过引入红黑树做了优化。当链表长度超过8,且数组容量大于64时,链表就会转换为红黑树,当红黑树的节点数量小于6时,会将红黑树转换为链表。

ps:在数据量较小的情况下,红黑树要消耗性能维护自身平衡,相较于链表性能而言没有优势。

4.场景应用

对于将list数据进行map处理,有以下两种方案

一.使用Set<Map.Entry<K,V>> entrySet()方案

Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法
1.public K getKey():获取Entry对象中的键。
2.public V getValue():获取Entry对象中的值。
3.在Map集合中也提供了获取所有Entry对象的
4. public Set<Map.Entry<K,V>> entrySet(): 
获取到Map集合中所有的键值对对象的集合(Set集合)。
1.获取Map集合中,所有的键值对 Entry对象 以Set的形式返回,entrySet()
2.遍历包含键值对 对象的 集合 拿到 每一对键值对 对象
3.通过键值对 对象 获取Entry对象中的键与值 方法提示 getKey() getValue()

//此处用于遍历循环判断同一个vin对应的list的相邻两条报文间隔时长是否大于15s从而进行分段---通过map遍历比查询效率高
1.首先分组构成map,map<vin,list<statistice>>
Map<String,List<statistice>> map = list.stream().collect(Collectors.groupingBy(statistice::getVin));
2.遍历map,根据不同的key值获取对应的value的list
for(Map.Entry<String, List<statistice>> entry : map.entrySet()){
//对value的list进行排序处理
   List<statistice>  newList = entry.getValue().stream().sorted(Comparator.comparing(statistice::getCollectTime)).collect(Collectors.toList());
   statistice beforestatistice = null;
   String currVin = entry.getKey();
   //遍历value的list,获取对象
   for (statistice statistice : newList){
      String xx = statistice.getHexString().substring(4,6);
      if (beforestatistice != null) {
         try {
            if(statistice != null){
            //按顺序两两相减
               if (sdf.parse(statistice.getCollectTime()).getTime() - sdf.parse(beforestatistice.getCollectTime()).getTime() > 15 * 1000L) {
                  cvList.add(currVin + "," + statistice.getCollectTime()+ "," + xx);
               }
            }
         } catch (ParseException e) {
            logger.error(e.getMessage());
         }
      }
   List<statistice>  newListDistinct = entry.getValue().stream().filter(distinctByKey(statistice::getGeneralWarnTagError)).collect(Collectors.toList());
   for (statistice statisticeDistinct : newListDistinct){
      String xx = statisticeDistinct.getHexString().substring(4,6);
      cvList.add(currVin + "," + statisticeDistinct.getCollectTime()+ "," + xx);
   }
}

 二.使用jdk8 的stream流模式

//通过stream流模式进行分组形成map
Map<String, List<mgtEntity>> map = listDistinctForCout.stream().collect(Collectors.groupingBy(
	a -> StringUtil.format("{0}#{1}#{2}#{3}#{4}#{5}", 		
	a.getCarType(),a.getVin(),a.getAlarmLevel(),a.getAlarmItem(),a.getDataType(),a.getRecoveryTime())));
List<mgtEntity>  cvListForDistinct = new ArrayList<>();
//对map进行遍历,根据遍历key获取对应的list  value
for(Map.Entry<String, List<mgtEntity>> entry : map.entrySet()){
    List<mgtEntity> newList = entry.getValue().stream().sorted(Comparator.comparing(mgtEntity::getAlarmTime)).collect(Collectors.toList());
    mgtEntity beforemgtEntity = null;
    对获取的list value进行遍历,获取对象
    for (mgtEntity mgtEntityList : newList){
        if (beforemgtEntity != null) {
            try {
                if (sdf.parse(mgtEntityList.getAlarmTime()).getTime() > sdf.parse(beforemgtEntity.getAlarmTime()).getTime() ) {
                    cvListForDistinct.add(beforemgtEntity);
                }
            } catch (ParseException e) {
                logger.error(e.getMessage());
            }
        }else{
            cvListForDistinct.add(mgtEntityList);
        }
        beforemgtEntity = mgtEntityList;
    }
}

ps:map的get使用

public static void main(String[] args) {
	//map使用put
    Map<String, String[]> map = new HashMap<>();
    String[] values = new String[]{"/userManage/**","/persjar/**","/RNR/**","/FlowCtrl/**"};
    map.put("admin", values);
    String[] values2 = new String[]{"/persjar/**","/RNR/**","/FlowCtrl/**"};
    map.put("user", values2);
    System.out.println(antPathMatcher("/userManage/addUser", map.get("user")));
    //list使用add
    Set<String> roles = new HashSet<>();
    roles.add("user");
    roles.add("admin");
}

猜你喜欢

转载自blog.csdn.net/qq_41429436/article/details/121989187