Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Java列表中删除所有重复的字符串?_Java_Arraylist_Collections_Set - Fatal编程技术网

如何从Java列表中删除所有重复的字符串?

如何从Java列表中删除所有重复的字符串?,java,arraylist,collections,set,Java,Arraylist,Collections,Set,对于给定的列表,假设[“a”、“a”、“b”、“c”、“c”]我需要[“b”](仅非重复元素)作为输出。请注意,这与使用作业的Set界面不同 我用Java编写了以下代码: void unique(List<String> list) { Collections.sort(list); List<String> dup = new ArrayList<>(); int i = 0, j = 0; for (String e :

对于给定的列表,假设
[“a”、“a”、“b”、“c”、“c”]
我需要
[“b”]
(仅非重复元素)作为输出。请注意,这与使用作业的
Set
界面不同

我用Java编写了以下代码:

void unique(List<String> list) {
    Collections.sort(list);
    List<String> dup = new ArrayList<>();
    int i = 0, j = 0;

    for (String e : list) {
        i = list.indexOf(e);
        j = list.lastIndexOf(e);

        if (i != j && !dup.contains(e)) {
            dup.add(e);
        }
    }

    list.removeAll(dup);
}
void unique(列表){
集合。排序(列表);
List dup=new ArrayList();
int i=0,j=0;
for(字符串e:列表){
i=列表索引f(e);
j=列表的最后索引xof(e);
如果(i!=j&!重复包含(e)){
重复添加(e);
}
}
列表。删除所有(dup);
}

它是有效的。。。但对于85320大小的列表,几分钟后结束

你可以使用地图。执行以下操作

1. Create a map of following type Map<String, Integer>
2. for all elements
       check if the string is in hashmap
             if yes then increment the value of that map entry by 1
       else add <current element , 1>
3. now your output are those entries of the Map whose values are 1.
1。创建以下类型的映射映射
2.适用于所有元素
检查字符串是否在hashmap中
如果是,则将该映射条目的值增加1
其他添加
3.现在,您的输出是那些值为1的映射条目。

您的最佳性能是通过设置:

    String[] xs = { "a", "a", "b", "c", "c" };

    Set<String> singles = new TreeSet<>();
    Set<String> multiples = new TreeSet<>();

    for (String x : xs) {
        if(!multiples.contains(x)){
            if(singles.contains(x)){
                singles.remove(x);
                multiples.add(x);
            }else{
                singles.add(x);
            }
        }
    }
String[]xs={“a”、“a”、“b”、“c”、“c”};
Set singles=new TreeSet();
设置倍数=新树集();
for(字符串x:xs){
如果(!multiples.contains(x)){
if(singles.contains(x)){
单打。移除(x);
倍数。加(x);
}否则{
单打。加(x);
}
}
}

这是一个单次传递,插入、删除和包含的是日志(n)。

鉴于您可以对列表进行排序,最有效的方法是使用
列表迭代器来迭代相邻元素的运行:

List<String> dup = new ArrayList<>();
Collections.sort(list);
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
  String first = it.next();

  // Count the number of elements equal to first.
  int cnt = 1;
  while (it.hasNext()) {
    String next = it.next();
    if (!first.equals(next)) {
        it.previous();
        break;
    }
    ++cnt;
  }

  // If there are more than 1 elements between i and start
  // it's duplicated. Otherwise, it's a singleton, so add it
  // to the output.
  if (cnt == 1) {
    dup.add(first);
  }
}

return dup;
List dup=new ArrayList();
集合。排序(列表);
ListIterator it=list.ListIterator();
while(it.hasNext()){
String first=it.next();
//计算等于第一个元素的元素数。
int-cnt=1;
while(it.hasNext()){
String next=it.next();
如果(!first.equals(next)){
it.previous();
打破
}
++碳纳米管;
}
//如果在i和start之间有超过1个元素
//它是重复的。否则,它是一个单例,所以添加它
//到输出。
如果(cnt==1){
重复添加(第一);
}
}
返回dup;

ListIterator
对于不支持随机访问的列表(如
LinkedList
)比使用基于索引的访问更有效。

您可以使用
streams
通过以下带有内联注释的简单步骤来实现这一点:

//Find out unique elements first
List<String> unique = list.stream().distinct().collect(Collectors.toList());

//List to collect output list
List<String> output = new ArrayList<>();

//Iterate over each unique element
for(String element : unique) {

    //if element found only ONCE add to output list
    if(list.stream().filter(e -> e.equals(element)).count() == 1) {
        output.add(element);
    }
}
//首先找出唯一的元素
List unique=List.stream().distinct().collect(Collectors.toList());
//列表以收集输出列表
列表输出=新的ArrayList();
//迭代每个唯一的元素
for(字符串元素:唯一){
//如果只找到一次元素,则将其添加到输出列表中
if(list.stream().filter(e->e.equals(element)).count()==1){
输出。添加(元素);
}
}
使用Java 8流:

return list.stream()
    .collect(Collectors.groupingBy(e -> e, Collectors.counting()))
    .entrySet()
    .stream()
    .filter(e -> e.getValue() == 1)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

我可能是一个很好的算法问题。列表的值是否受到某种程度的限制(例如仅ascii字符)?如果一个元素出现的次数超过1,则必须从列表中删除其所有出现的次数。@Thorbjørnravandersen我不相信OP是说不允许使用Set-只是所需的输出并不仅仅是从
新哈希集(list)中获得的结果
@AndyTurner抓住了重点。没错@然后这个问题的标题写得很糟糕。LinkedHashSet呢?可能更快,这取决于散列的好坏,可能需要更多的内存。我正在为每个数据项使用本机(Java)字符串。所以,我希望它有一个非常好的散列。问题的标题中有“不使用集合”
TreeSet
是一个
集合
…注意:您可以使用
if(singles.remove(x))
而不是调用contains然后remove。在我的PCB中大约需要50-55秒,但他不想使用集合或类似的集合datastructure@prasanth我不确定OP所说的“未设置”-我将其解释为,它并不是简单地执行集合将执行的操作,因为期望的输出不仅仅是不同的值。标题是“不使用集合”。这就是我的意思。@nazar_art缺少括号(和missing.stream())。现在补充说。我不太喜欢java流的原因(当它们提供更简单的解决方案时,我仍然使用它们)是因为它们无法实现简洁性和清晰性,在scala中相同的语句是
list groupBy identity collect{case(k,+:Nil)=>k}
@减去我认为罪魁祸首是
.collect(…)
部分。整个收集器场景相当复杂,可能超出了需要,Java只允许一个返回值也无济于事。我完全同意,收集器很难使用(也很难记住),从流到集合的来回切换会添加很多样板文件。