感谢
文章是我按照我的bug和debug过程写的,这里感谢这篇文章的帮助:http://www.2cto.com/kf/201506/410713.html
背景
最近在弄一个通讯录导入小功能:【A操作】读取通讯录-获得列表-选择你想要的某些联系人-保存到安卓客户端。
但是遇到个问题:当你导入成功后,【B操作】想再导入几个联系人的时候。再走一遍上述流程,你会发现,通讯录和你本地有重复的数据
那么问题来了:通讯录是一个列表, 客户端本地也有一个列表。我们需要把通讯录读取后,移除我们本地的数据。展示出来的全是未导入的数据
案例
contains 1
说到一个List里包含某个*, 会不会想到Contains?最常见的是这样的:
public void main1(){
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王二麻子");
String aimString1 = "李四";
String aimString2 = "我不是黄蓉";
if(list.contains(aimString1)) {
Log.i("是否包含?", "包含了-李四");
}
Log.i("是否包含?", "包含了-我不是黄蓉?"+list.contains(aimString2));
}
打印如下:
I/是否包含?﹕ 包含了-李四
I/是否包含?﹕ 包含了-我不是黄蓉?false
可以看到Contains很完美的实现了我们的目标!你以为这样这篇文章就结束了?NoNoNo ~
contains 2
如果我们要比对的不是String类型,而是一个下面的自定义类呢?
public class userInfo {
private int _id ;
private String name ;
private String phone ;
public userInfo(String name){
this.name = name ;
}
// getter和setter略去
}
测试代码小改动了下,如下:
public void main2() {
ArrayList<userInfo> list = new ArrayList<>();
list.add(new userInfo("张三"));
list.add(new userInfo("李四"));
list.add(new userInfo("王二麻子"));
userInfo aimUser1 = new userInfo("李四");
if (list.contains(aimUser1)) {
Log.i("是否包含?", "包含了-李四");
} else {
Log.i("是否包含?", "我擦,居然没包含?不科学啊");
}
}
打印如下:
I/是否包含?﹕ 我擦,居然没包含?不科学啊
contains 进阶
有问题就找嘛,我们按住Ctrl点击contains来看源码:
@Override public boolean contains(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
return true;
}
}
}
return false;
}
PS:系统有啥叼的嘛, 还不是用for循环挨个对比的
里面用到了
object.equals(a[i])
其源码是
public boolean equals(Object o) {
return this == o;
}
其实这里面的Object就是我们上面的自定义类userInfo 这上面的源码居然用 this==o 来对比两个实体?这就是判断两者的地址是否相等嘛。
可是我们需要的是两者的内容相等
按照文章开头那里感谢的那篇文章,在我们的实体类中重写equals方法,没啥难的,我们一起来看:
public class userInfo {
private int _id ;
private String name ;
private String phone ;
public userInfo(String name){
this.name = name ;
}
// getter和setter略去
@Override
public boolean equals(Object o) {
if(o instanceof userInfo) {
// 类型强转
userInfo _userInfo = (userInfo) o ;
// // 仅仅比对name
// return this.name.equals(_userInfo.getName()) ;
// 比对三个参数
return this.name.equals(_userInfo.getName()) &&
this.phone.equals(_userInfo.getPhone()) &&
this._id == _userInfo.get_id();
}
return super.equals(o);
}
}
这时候再跑一次code ,崩~ NullPointerException
String crash = null ;
Log.i("log", "result:"+crash.equals("oh no !"));
equals前面是不能为null的。那怎么办? 我怎么知道。。。 尽量避免不让其为null呗,或者你加判断试试?顺便说一句,下面的写法比较好:
String crash = null ;
Log.i("log", "result:"+"oh no !".equals(crash));
实战
一开始就说到是一个导入通讯录的小任务嘛,上面一直是举例子,这下轮到实战了。不过我不想写了。任性一回 。
疑问
我一直想知道 List中我通过contains得知了是否包含,但是位置怎么获取呢?