常见集合去重复的几种实现
admin 发布于:2013-09-08 00:53:00
阅读:loading
在写这个之前,总喜欢割一下=============在平时工作中,有个很小很小的实现就是对某个集合元素的去除重复项,以前也肯定处理过,不过记不得了,今天又遇到了,这里就总结一下这个很小很小的实现的解决方案吧,以及再介绍一下熟悉的其他的实现方案的实现。
先说一下业务场景吧,假设有个集合,它的定义如下:
List<String> dataList = new ArrayList<String>();
dataList.add("aa");
dataList.add("bb");
dataList.add("bb");
dataList.add("cc");
dataList.add("cc");
dataList.add("dd");
dataList.add("ee");
在处理一个简单类型的集合去重复是比较简单的,在我看来想都不用想的办法是使用Set集合,即将List集合转换为Set集合,使用Set集合不能存储重复元素的特性,简单的代码实现为:
Set<String> dataSet = new HashSet<String>();
dataSet.addAll(dataList);
System.out.print(dataSet);
以上的代码输出的结果为: [dd, ee, aa, bb, cc]
注意由于以上的set结合会打乱原有集合的先后顺序,如果想保持原有顺序的话,将以上的HashSet换成LinkedHashSet,这个原因大家都知道不解释了。
实际上上面的业务也是很不科学的,因为基本上很少直接有需要处理去重复的集合里面是一个简单的类型,或者说一个集合中的某些对象,其中某一个属性值相等就可以认为它是重复的,那么如此上述的业务需求将需要改写,将重新定义一个集合,且赋上初始化数据,代码如下:
class User {
private Integer id;// 用户编号
private String name;// 用户姓名
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append('{').append("id : ").append(this.id).append(',')
.append(" name : ").append(this.name).append('}');
return builder.toString();
}
}
List<User> userList = new ArrayList<User>();
userList.add(new User(1 , "weiyan"));
userList.add(new User(2 , "zhoutai"));
userList.add(new User(3 , "yujin"));
userList.add(new User(4 , "xiahoudun"));
userList.add(new User(1 , "xuchu"));
userList.add(new User(2 , "mashu"));
userList.add(new User(3 , "yuanshao"));
userList.add(new User(4 , "gongsun2"));
这种数据直接使用Set集合肯定是不行的,个人推荐使用以下两种方式实现:
方法一:将集合中能够区别为重复的属性作为map集合的key,对应的对象作为value,注意如果需要多个属性判断相等为重复元素,则可以采用多个属性相加的方式,参考实现代码如下:
Map<Integer, User> userMap = new HashMap<Integer, User>();
for (User user : userList) {
Integer key = user.getId();
if (userMap.containsKey(key) == false) {
userMap.put(key, user);
}
}
List<User> newList = new ArrayList<User>();
Set<Entry<Integer, User>> userSet = userMap.entrySet();
for (Entry<Integer, User> entry : userSet) {
User user = entry.getValue();
newList.add(user);
}
System.out.println(newList);
上述代码输出的结果为: [{id : 1, name : weiyan}, {id : 2, name : zhoutai}, {id : 3, name : yujin}, {id : 4, name : xiahoudun}]
方法二:使用两层循环来解决,参考代码如下:
for(int i = userList.size() - 1 ; i >= 0 ; i-- ){
User user1 = userList.get(i);
for(int j = userList.size() - 1; j > i ; j--){
User user2 = userList.get(j);
if(user1.getId().equals(user2.getId())){
userList.remove(user1);
break;
}
}
}
System.out.println(userList);
以上代码输出的结果为:[{id : 1, name : xuchu}, {id : 2, name : masu}, {id : 3, name : yuanshao}, {id : 4, name : gongsun2}]
个人觉得两种方法实现都很简单,第二种方法就类似于sql查询中坑货们常用的笛卡尔积运算,更坑的是这里不加上break
至于还有好多种方法不提了,有很多人肯定喜欢用重写equals函数和hashCode函数来实现,这里就不那这种实现来说道了,一般的实现中,我想很多人还是不会考虑那种大师实现吧。
点赞