最近碰到一个坑,看代码:
@Test
public void should_can_get_true_when_given_matched_type() {
List numberList = Lists.newArrayList(1, 2, 34, 4);
Boolean contain = numberList.contains(2);
assertThat(contain).isTrue();
}
@Test
public void should_can_get_false_when_given_not_matched_type() {
List numberList = Lists.newArrayList(1, 2, 34, 4);
Boolean contain = numberList.contains(2L);// List 去判断 Long 类型元素
assertThat(contain).isFalse();
}
这里更改了待判断参数类型,并不报错,只是返回 false。
以ArrayList 为例,发现源码如下:
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
而对于包装类型,复写了equals方法
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
也就是说,对于同类型的对象,才去比较值来判断是否“相等”。
有些集合的原生函数不建议使用,比如Collections.contains/remove/Object.equals等。
@Component
public class MyCollectionUtils {
public Boolean contained(Collection collection, T element) {
return collection.contains(element);
}
}
使用时,明确指定要检测的元素类型。
@Autowired
private MyCollectionUtils myCollectionUtilsInteger;// 对集合和待检查元素都校验类型
@Autowired
private MyCollectionUtils myCollectionUtilsString;
@Test
public void should_can_get() {
Boolean result = myCollectionUtilsInteger.contained(Lists.newArrayList(1, 2, 34, 4), 2);
assertThat(result).isTrue();
}
@Test
public void should_can_get2() {
Boolean result = myCollectionUtilsString.contained(Lists.newArrayList("2", "s", "s", "333"), "2");
assertThat(result).isTrue();
}
每次根据需要注入不同类型的校验工具对象,检查性很强,不过这样做也有缺点,就是不同类型时,产生多个对象。
代码差不多,只不过只作为一个静态函数而已。
public class MyCollectionUtils {
public static Boolean contains(Collection collection, T element) {
return collection.contains(element);
}
}
使用时,如果类型不一致,编译报错。
@Test
public void should_compile_error_when_given_un_matched_type() {
List numberList = Lists.newArrayList(1, 2, 34, 4);
// MyCollectionUtils.contains(numberList, 2L);
// 类型不一致,直接编译错误
}