栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

CollectionUtils扩展方法(注:去重方法中有线程安全问题)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CollectionUtils扩展方法(注:去重方法中有线程安全问题)

一.代码示例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
 
import com.ibatis.common.beans.Probe;
import com.ibatis.common.beans.ProbeFactory;

public class CollectionUtilsExtends {
    
    private CollectionUtilsExtends (){}
    //1.根据属性名称获取属性值,后面详解
    private static final Probe PROBE = ProbeFactory.getProbe();

  //2.去重list集合中的null值,后面详解
    @SuppressWarnings("rawtypes")
    public static final Collection NULL_COLLECTION = new NullCollection();
      
    @SuppressWarnings("unchecked")
    public static final Collection nullCollection() {
        return (List) NULL_COLLECTION;
    }
    
    
    public static List getAllFormMap(List keys,Map source) {
        List values = Collections.emptyList();
        if (keys != null && !keys.isEmpty() && source != null && !source.isEmpty()) {
            values = new ArrayList();
            for (K k : keys) {
                values.add(source.get(k));
            }
        }
        return values;
    }
    
   
    public static List getValueList(List list, String valueProp) {
        List valueList = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(list)) {
            list.removeAll(nullCollection());
            valueList = new ArrayList(list.size());
            for (E e : list) {
                @SuppressWarnings("unchecked")
                K value = (K)PROBE.getObject(e, valueProp);
                valueList.add(value);
            }
        } 
        return valueList;
    }
    
   
    @SuppressWarnings("unchecked")
    public static Map listforMap(List list, String keyProp, String valueProp) {
        Map map = Collections.emptyMap();
        if (CollectionUtils.isNotEmpty(list)) {
            list.removeAll(nullCollection());
            map = new HashMap(list.size());
            for (E object : list) {
                K key = (K)PROBE.getObject(object, keyProp);
                Object value = null;
                if (StringUtils.isEmpty(valueProp)) {
                    value = object;
                } else {
                    value = PROBE.getObject(object, valueProp);
                }
                map.put(key, (V)value);
            }
        }
        return map;
    }
    
    
    @SuppressWarnings("unchecked")
    public static Map> listforListMap(List list, String keyProp,
            String valueProp) {
        Map> map = Collections.emptyMap();
        if (CollectionUtils.isNotEmpty(list)) {
            list.removeAll(nullCollection());
            map = new HashMap>(list.size());
            V value = null;
            for (E object : list) {
                K key = (K)PROBE.getObject(object, keyProp);
                if (StringUtils.isEmpty(valueProp)) {
                    value = (V)object;
                } else {
                    value = (V)PROBE.getObject(object, valueProp);
                }
                List values = map.get(key);
                if (values == null) {
                    values = new ArrayList();
                }
                values.add(value);
                map.put(key, values);
            }
        }
        return map;
    }

 

//3.涉及到线程安全问题,后面详解

public static List distinctByKey(List list, String valueProp) {

List resultList = Collections.synchronizedList(new ArrayList<>());

if (list.isEmpty() || StringUtils.isEmpty(valueProp)) {

return null;

}

list.parallelStream().filter(distinctByKey(p -> PROBE.getObject(p, valueProp))).forEach(resultList ::add);
}

public static   Predicate distinctByKey(Function keyExtractor) {

  Map seen = new ConcurrentHashMap<>();

  return t->seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;

}

}

二.技术点: 1.使用ProbeFactory.getProbe().getObject()根据属性名称获取属性值:

依赖:



    com.ibatis
    ibatis2-common
    2.1.7.597

2.去重list集合中的null值,使用NullCollection,代码如下:

import java.io.Serializable;  
import java.util.AbstractList;  
import java.util.RandomAccess;  
  
public class NullCollection extends AbstractList  
implements RandomAccess, Serializable  {  
  
    private static final long serialVersionUID = 5206887786441397812L;  
  
    @Override  
    public Object get(int index) {  
        return null;  
    }  
  
    @Override  
    public int size() {  
        return 1;  
    }  
      
    public boolean contains(Object obj) {  
        return null == obj;  
    }  
      
    private Object readResolve() {  
        return null;  
    }  
}  

3.去重过程中遇到线程安全问题

3.1 使用parallelStream并行流对list集合进行读写操作,list是线程不安全,导致出现问题:

解决:1.parallelStream并行流改成stream串行流

            2.保证list集合线程安全

谈谈并行流parallelStream_SunAlwaysOnline的博客-CSDN博客_parallelstream

3.2 list线程安全

   Java 中最常用的集合为:ArrayList 和 LinkedList,但这两个线程并非是线程安全的,在多线程情况就需要考虑线程安全的 List:

   1.Vector 是在 JDK 1.0 中加入的,历史悠久;
      底层原理和 ArrayList 几乎一致,区别在于 Vector 每个公开的方法上都加入          了 synchronized 保证并发安全,但性能非常低下,不推荐使用;

   2.Collections.synchronizedList()

      Collections 集合工具类提供了一个方法可以将 List 转为线程安全的 SynchronizedList

      public static List synchronizedList(List list)

    原理仅是在每个方法上加上了 synchronized 来保证线程安全,相比于 Vector 扩展性,灵活性更高;

    3.CopyOnWriteArrayList & CopyOnWriteArraySet

     利用写时复制(COW)实现线程安全的集合,优点是有现成进行修改的时候,仍有其他线程可以读取,缺点是浪费空间,每次添加删除元素就需要复制一份新数组。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号