在 Java 中,有没有更优雅的方法从字符串的 ArrayList 中删除重复的字符串?

Posted

技术标签:

【中文标题】在 Java 中,有没有更优雅的方法从字符串的 ArrayList 中删除重复的字符串?【英文标题】:In Java, is there a more elegant way to remove duplicate strings from and ArrayList of Strings? 【发布时间】:2012-10-31 11:56:57 【问题描述】:

所以,长话短说,我有一个 Java 家庭作业,需要以各种方式操作一个长的字符串数组列表(我们正在做一些事情,比如显示单词的组合,在 ArrayList 中添加和删除,什么也没有特别的)。我注意到一些提供的 ArrayLists 有重复的条目(并且重复项对于此作业不是必需的),所以我得到老师的同意,可以通过删除重复的条目来清理数据。 这是我想出的:

private static ArrayList<String> KillDups(ArrayList<String> ListOfStrings)   

    for (int i = 0 ; i < ListOfStrings.size(); i++) 
        for (int j = i + 1; j < ListOfStrings.size(); j++) 
            //don't start on the same word or you'll eliminate it.
            if ( ListOfStrings.get(i).toString().equalsIgnoreCase( ListOfStrings.get(j).toString() )  ) 
                ListOfStrings.remove(j);//if they are the same, DITCH ONE.
                j = j -1; //removing the word basically changes the index, so swing down one.
                                            
        
    
    return ListOfStrings;

这对我的任务来说很好,但我怀疑它在现实世界中是否非常有用。有没有办法在比较过程中忽略空格和特殊字符?一般有没有更清洁的方法来处理这个问题(可能没有嵌套的 For 循环)?还有一个我不知道该问的问题吗?

【问题讨论】:

首先:你不需要toString 无处不在,因为这些已经是字符串了。对于您的问题:我相信有很好的内置方法可以做到这一点。如果您想编写自己的,您可以简单地对列表进行排序并仅比较相邻条目以查看它们是否相等。这会给你 O(N) 的时间复杂度(不包括用于排序的 O(NlogN))。 由于相当多的答案似乎集中在你没有提到的东西上,如果 OP 能澄清一下,那就太好了:1)在删除重复后,你需要保持列表的顺序吗? 2)当您通过忽略大小写比较删除重复项时,您是否要保留第一个或最后一个字符串(或者您根本不在乎?)? 好吧,事实上,在这种情况下顺序并不重要。但是,由于我希望最终结果更有用,因此最好保留原始顺序。 【参考方案1】:

是的。只需 1 行(优雅)即可完成:

List<String> noDups = new ArrayList<String>(new LinkedHashSet<String>(list));

中间 Set 确保没有重复。选择 SetLinkedHashSet 实现以保留列表的顺序。

另外,关于风格说明:

以小写字母开头的名称命名您的方法和参数 在指定方法签名时始终引用抽象(即List)而不是具体(即ArrayList

那么你的整个方法是:

private static List<String> killDups(List<String> list) 
    return new ArrayList<String>(new LinkedHashSet<String>(list));

对于额外的brownie points,请将该方法设为通用,因此它适用于任何类型的List

private static <T> List<T> killDups(List<T> list) 
    return new ArrayList<T>(new LinkedHashSet<T>(list));

如果您想忽略某些字符,我会为此创建一个类并列出这些字符。 hashCode()equals() 方法都依赖于 HashSets 来删除重复:

public class MungedString 
    // simplified code
    String s;

    public boolean equals(Object o) 
        // implement how you want to compare them here
    

    public int hashCode() 
        // keep this consistent with equals()
    

然后

List<MungedString> list;
List<MungedString> noDupList = killDups(list);

【讨论】:

感谢您提供的一站式解决方案,以及额外的建议!我会尽我所能在未来赚取一些布朗尼积分。 :D【参考方案2】:

您可以使用 HashSet 代替 ArrayList。它是一个自动丢弃重复项的容器。确定插入的项目是否重复是一个常数时间操作,无论集合有多大。因此,将您的 ArrayList 转换为 HashSet 并返回将删除所有重复项。

缺点是 HashSet 的顺序是不可预测的,所以当维护顺序很重要时,请改用LinkedHashSet(这有点慢)。

【讨论】:

【参考方案3】:

考虑使用Set

对于最简单的情况,即直接比较字符串,使用Hashset 是您想要做的:

Set<String> mySet = new HashSet<String>();

mySet.addAll(aListWithDuplciatedStrings);

那么,mySet 中的内容将是唯一的字符串集。

对于忽略大小写的比较,这是我留给你的作业。看TreeSetComparator

【讨论】:

LinkedHashSet 将保持Strings 包含在List&lt;String&gt; 中的顺序。 是的,但我相信这不是 OP 要求的。【参考方案4】:

首先,您可以使用 Set 的漂亮单行来完成此操作:

private static ArrayList<String> KillDups(ArrayList<String> ListOfStrings) 
    return new ArrayList(new LinkedHashSet(ListOfStrings));

这将删除所有重复项。带有循环的第二个选项是将它们添加到新的List

private static ArrayList<String> KillDups(ArrayList<String> ListOfStrings) 
    ArrayList<String> newList = new ArrayList<String>();
    for(String s : ListOfStrings) 
        if(!newList.contains(s)) 
            newList.add(s);
        
    
    return newList

至于自定义比较。我相信有一个集合可以让你提供一个比较器,但是我现在不记得了。

【讨论】:

【参考方案5】:
import java.awt.Toolkit;
import java.util.Scanner;

class duplicate 

 public static void main(String[] args)   

    Scanner kb = new Scanner(System. in );
    System.out.println("Entre String");
    String string = kb.nextLine();


    int length = string.length();
    if(length < 2) 
        System.out.println(string);
        return;
    

    System.out.print(string.charAt(0));
    for (int i = 1; i < length; i++) 
        if (string.charAt(i) != string.charAt(i - 1)) 
            System.out.print(string.charAt(i));
           
    


【讨论】:

【参考方案6】:
public static void removeDuplicateString(String input) 
    String value1 = manikandan;
    String value2 = manikandan;
    String finalValue = "";
    int count = 0;
    char char1;
    char char2 = 0;
    for (int i = 0; i < value1.length(); i++) 
        flag = 0;
        char1 = value1.charAt(i);
        for (int j = 0; j < value2.length(); j++) 
            char2 = value2.charAt(j);
            if (char1 == char2) 
                count++;
            
        

        if (count > 1) 
            finalValue=finalValue+char1;
            i=i+(count-1);
         else 
            finalValue = finalValue + char1;
        
        count = 0;
    
    System.out.println(finalValue);

【讨论】:

以上是关于在 Java 中,有没有更优雅的方法从字符串的 ArrayList 中删除重复的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

Java字符串碎片

有没有更优雅的方式将项目安全地添加到 Dictionary<> 中?

在 Java 6 中等待方法结果(超时)的更优雅的方式

java多线程 更优雅的实现线程同步:交替打印AB LockSupport实现

有没有更优雅的方法来减少这种积极/消极的逻辑?

有没有更优雅的方法来添加可为空的整数?