删除Java中的List中的重复字符串

时间:2012-12-26 12:04:44

标签: java collections set

更新: 我猜HashSet.add(Object obj)不会调用contains。有没有办法实现我想要的东西(使用Set删除重复字符串忽略大小写?)

原始问题: 试图从java中的String列表中删除重复项,但是在下面的代码中CaseInsensitiveSet.contains(Object ob)没有被调用,为什么?

public static List<String> removeDupList(List<String>list, boolean ignoreCase){
    Set<String> set = (ignoreCase?new CaseInsensitiveSet():new LinkedHashSet<String>());
    set.addAll(list);

    List<String> res = new Vector<String>(set);
    return res;
}


public class CaseInsensitiveSet  extends LinkedHashSet<String>{

    @Override
    public boolean contains(Object obj){
        //this not getting called.
        if(obj instanceof String){

            return super.contains(((String)obj).toLowerCase());
        }
        return super.contains(obj);
    }

}

5 个答案:

答案 0 :(得分:7)

尝试

        Set set = new TreeSet(String.CASE_INSENSITIVE_ORDER);
        set.addAll(list);
        return new ArrayList(set);

更新但正如Tom Anderson所说,它不会保留初始订单,如果这确实是个问题,请尝试

    Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
    Iterator<String> i = list.iterator();
    while (i.hasNext()) {
        String s = i.next();
        if (set.contains(s)) {
            i.remove();
        }
        else {
            set.add(s);
        }
    }

打印

[2, 1]

答案 1 :(得分:5)

contains未被调用,因为LinkedHashSet没有以这种方式实现。

如果你想要add()来调用contains(),你也需要覆盖它。

它没有以这种方式实现的原因是首先调用包含意味着你正在执行两次查找而不是一次更慢的查找。

答案 2 :(得分:3)

add()的{​​{1}}方法不会在内部调用LinkedHashSet,否则您的方法也会被调用。

而不是contains(),为什么不使用LinkedHashSet与不区分大小写的比较器 ?使用String.CASE_INSENSITIVE_ORDER比较器

您的代码缩减为

SortedSet

如果您希望保留订单,如@tom anderson在其评论中指定的那样,您可以使用辅助LinkedHashSet作为订单。

您可以尝试将该元素添加到TreeSet中,如果它返回true也将其添加到LinkedHashSet中,否则不会。

public static List<String> removeDupList(List<String>list, boolean ignoreCase){
    Set<String> set = (ignoreCase?new TreeSet<String>(String.CASE_INSENSITIVE_ORDER):new LinkedHashSet<String>());
    set.addAll(list);

    List<String> res = new ArrayList<String>(set);
    return res;
}

答案 3 :(得分:0)

尝试

    public boolean addAll(Collection<? extends String> c) {
            for(String s : c) {
            if(! this.contains(s)) {
                this.add(s);
            }
        }
        return super.addAll(c);
    }
    @Override
    public boolean contains(Object o) {
        //Do your checking here
//      return super.contains(o);
    }

这将确保在您希望代码通过时调用contains方法。

答案 4 :(得分:0)

这是另一种方法,使用HashSet字符串进行重复数据删除,但直接构建结果列表:

public static List<String> removeDupList(List<String> list, boolean ignoreCase) {
    HashSet<String> seen = new HashSet<String>();
    ArrayList<String> deduplicatedList = new ArrayList<String>();
    for (String string : list) {
        if (seen.add(ignoreCase ? string.toLowerCase() : string)) {
            deduplicatedList.add(string);
        }
    }
    return deduplicatedList;
}

这非常简单,只对元素进行一次传递,并且只进行小写,哈希查找,然后为每个元素添加一个列表。

相关问题