前言
实际业务开发中,集合的判断和操作也是经常用到的,Spring也针对集合的判断和操作封装了一些方法,但是最令我惊讶的是,我在梳理这些内容的过程中发现了一些有趣的现象,我的第一反应是不敢相信,再想一想,没错,我是对的。所以强烈建议大家可以认真看完这篇文章,这一篇绝对有价值,因为有趣的是我我竟然发现了Spring的两个bug。
org.springframework.util.CollectionUtils
集合的判断
boolean hasUniqueObject(Collection collection)
从源码注释上看,是用于判断 List/Set 中的每个元素是否唯一,即 List/Set 中不存在重复元素。但这里要告诉大家千万不要用这个方法,因为这个方法有bug,为什么呢?下面是Spring-core-5.2.13.RELEASE.jar中的源码,且看12行,细心的人会发现两个对象之间比较是否相等用的是!=。还记得“==”和“equals”的区别吗?“==”操作符专门用来比较两个变量的值是否相等,equals()方法是用于比较两个独立对象的内容是否相同。所以这里如果集合中的元素是数值,可以用“==”比较,如果是普通的引用对象,就得不到正确的结果了。
public static boolean hasUniqueObject(Collection<?> collection) {
if (isEmpty(collection)) {
return false;
}
boolean hasCandidate = false;
Object candidate = null;
for (Object elem : collection) {
if (!hasCandidate) {
hasCandidate = true;
candidate = elem;
}
else if (candidate != elem) {
return false;
}
}
return true;
}
boolean containsInstance(Collection collection, Object element)
从源码的注释上看,是用于判断集合中是否包含某个对象。这个方法也不建议使用,因为与上一个方法存在相同的问题,且看源码的第4行,依然用的是“==”。
public static boolean containsInstance(@Nullable Collection<?> collection, Object element) {
if (collection != null) {
for (Object candidate : collection) {
if (candidate == element) {
return true;
}
}
}
return false;
}
boolean isEmpty(Collection collection)
这个方法已验证过可以放心用,用于判断 List/Set 是否为空;
@Test
public void test1(){
Collection<String> list=new ArrayList<>();
boolean empty = CollectionUtils.isEmpty(list);
Assert.isTrue(empty, "集合list不为空");
System.out.println("集合list增加一元素");
list.add("happy");
boolean empty2 = CollectionUtils.isEmpty(list);
Assert.isTrue(empty2, "集合list不为空");
}
boolean isEmpty(Map map)
用于判断 Map 是否为空。
@Test
public void test2(){
Map<String,String> map = new HashMap<>();
boolean empty = CollectionUtils.isEmpty(map);
Assert.isTrue(empty, "map不为空");
System.out.println("map中增加元素");
map.put("name", "jack");
boolean empty2 = CollectionUtils.isEmpty(map);
Assert.isTrue(empty2, "map不为空");
}
boolean containsAny(Collection source, Collection candidates)
从源码上的注释看,是用于判断集合source中是否包含另一个集合candidates的任意一个元素,即集合candidates中的元素是否完全包含于集合soruce。
从源码这个方法中的元素之间的比较用到了“equals”方法,且调用的是集合内对象的equals方法,因此使用这个方法想要得到正确的结果的前提是,比较的对象要重写hashCode()和eauals()方法。
@Test
public void test4(){
Employee lisi = new Employee("lisi");
Employee zhangsan = new Employee("zhangsan");
Employee wangwu = new Employee("wangwu");
List<Employee > list=new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
List<Employee> list2=new ArrayList<>();
list2.add(wangwu);
//这里可以用是因为比较的时候调用的是equals方法
boolean b = CollectionUtils.containsAny(list, list2);
Assert.isTrue(b, "list1没有包含有list2中任意一个元素");
}
集合的操作
void mergeArrayIntoCollection(Object array, Collection collection)
将数组array中的元素都添加到 List/Set 中。
@Test
public void test6(){
List<Employee > list=new ArrayList<>();
Employee lisi = new Employee("lisi");
list.add(lisi);
Employee zhangsan = new Employee("zhangsan");
Employee[] employees={zhangsan};
CollectionUtils.mergeArrayIntoCollection(employees, list);
Assert.isTrue(list.size()==2, "把数据中的元素合并到list失败了");
}
void mergePropertiesIntoMap(Properties props, Map map)
将 Properties 中的键值对都添加到 Map 中。
@Test
public void test7(){
Properties properties = new Properties();
properties.setProperty("name", "zhangsan");
Map<String,String > map = new HashMap<>();
CollectionUtils.mergePropertiesIntoMap(properties, map);
Assert.isTrue(map.get("name").equals("zhangsan"), "把properties中的元素合并到map中失败了");
}
T lastElement(List list)
返回 List 中最后一个元素。
@Test
public void test8(){
Employee lisi = new Employee("lisi");
Employee zhangsan = new Employee("zhangsan");
List<Employee > list=new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
Employee employee = CollectionUtils.lastElement(list);
Assert.isTrue(employee.equals(lisi), "获取集合最后一个元素失败了");
}
T firstElement(List list)
返回集合中第一个元素。
@Test
public void test9(){
Employee lisi = new Employee("lisi");
Employee zhangsan = new Employee("zhangsan");
List<Employee > list=new ArrayList<>();
list.add(zhangsan);
list.add(lisi);
Employee employee = CollectionUtils.firstElement(list);
Assert.isTrue(employee.equals(zhangsan), "获取集合第一个元素失败了");
}
List arrayToList(Object source)
把一个数组转换成一个集合。
@Test
public void test10(){
Employee zhangsan = new Employee("zhangsan");
Employee[] employees={zhangsan};
List list = CollectionUtils.arrayToList(employees);
Assert.isTrue(list.size()==1, "把数据转换成集合失败了");
}