一.技术点:
1.使用ProbeFactory.getProbe().getObject()根据属性名称获取属性值:
依赖:
<!-- https://mvnrepository.com/artifact/com.ibatis/ibatis2-common -->
<dependency>
<groupId>com.ibatis</groupId>
<artifactId>ibatis2-common</artifactId>
<version>2.1.7.597</version>
</dependency>
2.去重list集合中的null值,使用NullCollection,代码如下:
import java.io.Serializable;
import java.util.AbstractList;
import java.util.RandomAccess;
public class NullCollection extends AbstractList<Object>
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 <T> List<T> synchronizedList(List<T> list)
原理仅是在每个方法上加上了 synchronized
来保证线程安全,相比于 Vector
扩展性,灵活性更高;
3.CopyOnWriteArrayList & CopyOnWriteArraySet
利用写时复制(COW)实现线程安全的集合,优点是有现成进行修改的时候,仍有其他线程可以读取,缺点是浪费空间,每次添加删除元素就需要复制一份新数组。
4.Collections.emptyList() 方法的使用
4.1 emptyList()
作用:返回一个空的List(使用前提是不会再对返回的list进行增加和删除操作);
好处:
1. new ArrayList()创建时有初始大小,占用内存,emptyList()不用创建一个新的对象,可以减少内存开销;
2. 方法返回一个emptyList()时,不会报空指针异常,如果直接返回Null,没有进行非空判断就会报空指针异常;
注意:此List与常用的List不同,它是Collections类里的静态内部类,在继承AbstractList后并没有实现add()、remove()等方法,所以返回的List不能进行增加和删除元素操作。
4.2 如果需要对collections.emptyList()进行增删操作的话,就需要将collections.emptyList()转换成ArrayList()进行操作。
二.代码示例:
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 <T> Collection<T> nullCollection() {
return (List<T>) NULL_COLLECTION;
}
/**
* <pre>
* 批量获取map中的值
* </pre>
*
* @param <K>
* @param <V>
* @param keys
* @param source
* @return
*/
public static <K,V> List<V> getAllFormMap(List<K> keys,Map<K,V> source) {
List<V> values = Collections.emptyList();
if (keys != null && !keys.isEmpty() && source != null && !source.isEmpty()) {
values = new ArrayList<V>();
for (K k : keys) {
values.add(source.get(k));
}
}
return values;
}
/**
*
* <pre>
* 从List中获取valueProp组成一个新的list
* </pre>
*
* @param <E>
* @param list
* @param valueProp
* @return
*/
public static <E,K> List<K> getValueList(List<E> list, String valueProp) {
List<K> valueList = Collections.emptyList();
if (CollectionUtils.isNotEmpty(list)) {
list.removeAll(nullCollection());
valueList = new ArrayList<K>(list.size());
for (E e : list) {
@SuppressWarnings("unchecked")
K value = (K)PROBE.getObject(e, valueProp);
valueList.add(value);
}
}
return valueList;
}
/**
*
* <pre>
* 用list生成一个map,keyProp 为指定的key,valueProp 为指定是value
* </pre>
*
* @param <K>
* @param <V>
* @param <E>
* @param list
* @param keyProp
* @param valueProp
* @return
*/
@SuppressWarnings("unchecked")
public static <K,V,E> Map<K,V> listforMap(List<E> list, String keyProp, String valueProp) {
Map<K,V> map = Collections.emptyMap();
if (CollectionUtils.isNotEmpty(list)) {
list.removeAll(nullCollection());
map = new HashMap<K, V>(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;
}
/**
*
* <pre>
* list 生成一个Map<K,List<V>>
* </pre>
*
* @param <K>
* @param <V>
* @param <E>
* @param list
* @param keyProp
* @param valueProp
* @return
*/
@SuppressWarnings("unchecked")
public static <K,V,E> Map<K,List<V>> listforListMap(List<E> list, String keyProp,
String valueProp) {
Map<K, List<V>> map = Collections.emptyMap();
if (CollectionUtils.isNotEmpty(list)) {
list.removeAll(nullCollection());
map = new HashMap<K, List<V>>(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<V> values = map.get(key);
if (values == null) {
values = new ArrayList<V>();
}
values.add(value);
map.put(key, values);
}
}
return map;
}
/**
* <pre>
* 根据对象集合中的valueProp值进行去重
* </pre>
* @param <K>
* @param <V>
* @param list
* @param valueProp
* @return
*/
//3.涉及到线程安全问题,前面详解
public static <E> List<E> distinctByKey(List<E> list, String valueProp) {
List<E> 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);
}
/**
*distinctByKey 按照集合对象属性去重
*/
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t->seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}