判断一个list中是否有需要查找的对象,最土的方法就是遍历整个list进行比对,然后等全部遍历完,还找不到就返回一个结果。
有一个需求是这样的:有一个装有Map对象的List集合,Map中有id和type属性。需要判断list集合中是否有type=2的数据。
这里用Collections.binarySearch进行了实现。
binarySearch(List<? extends T>, T, Comparator<? super T>) 方法用于搜索指定列表,使用二进制搜索算法来指定对象。该列表必须根据指定的比较器按升序排列。
首先新建一个List:
List<Map<String, String>> list = new ArrayList<>();
往list中添加数据:
Map<String, String> map = new HashMap<String, String>();
map.put("id", "1");
map.put("type", "1");
list.add(map);
Map<String, String> map1 = new HashMap<String, String>();
map1.put("id", "2");
map1.put("type", "2");
list.add(map1);
新建若个map进行比对
Map<String, String> map2 = new HashMap<String, String>();
map2.put("id", "3");
map2.put("type", "3");
Map<String, String> map3 = new HashMap<String, String>();
map3.put("id", "2");
map3.put("type", "2");
Map<String, String> map4 = new HashMap<String, String>();
map4.put("id", "1");
map4.put("type", "2");
用binarySearch方法进行操作:
int index = Collections.binarySearch(list, map2, new Comparator<Map<String, String>>() {
@Override
public int compare(Map<String, String> o1, Map<String, String> o2) {
return o1.get("type").compareTo(o2.get("type"));
}
});
最后的执行结果分别为:
-3 1 1
当结果大于等于0时,表示存在,结果即为存在的索引
这里引用下源码说明下原理:
private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
int low = 0;
int high = l.size()-1;
ListIterator<? extends T> i = l.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
T midVal = get(i, mid);
int cmp = c.compare(midVal, key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
int cmp = c.compare(midVal, key);
在上面这行代码中,因为调用的是我们本地生成的比较器,而我们本地的比较器是根据type来进行比较的,如果type值相同,那么cmp=0,即返回当前对象的索引值