如何从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只允许一个返回值也无济于事。我完全同意,收集器很难使用(也很难记住),从流到集合的来回切换会添加很多样板文件。