在一次采访中,人们被要求在两个字符串数组之间找到非常见的元素。
Eg: String a[]={"a","b","c","d"};
String b[]={"b","c"};
O/p should be a,d
我已回答了Java Set中使用HashTable实现的问题。使用Set的代码更简单:
String[] a = {"a","b","c","d"};
String[] b = {"b", "c"};
Set<String> set = new HashSet<>(a.length);
for(String s : a){
set.add(s);
}
for(String s : b){
set.remove(s);
}
return set;
现在我的疑问是,有没有其他更好的方法来实现这个
答案 0 :(得分:6)
如果[x,y], [x,z]
应该产生[y,z]
这就是我的建议:
String[] a = {"a","b","c","d"};
String[] b = {"b", "c", "x"};
Set<String> set = new HashSet<>(Arrays.asList(a));
for (String s : new HashSet<>(Arrays.asList(b)) {
if (!set.add(s)) // if it's already present
set.remove(s); // remove it from the result
}
如果另一方面,[x,y], [x,z]
应该产生[y]
,我会建议
Set<String> set = new HashSet<>(Arrays.asList(a));
set.removeAll(Arrays.asList(b));
答案 1 :(得分:6)
答案 2 :(得分:5)
实际上,这扩展了Jon Skeet的答案,但使用Java 8的流程。
String[] result = Arrays.stream(a)
.filter((s) -> Arrays.stream(b).noneMatch(s::equals))
.toArray(String[]::new);
System.out.println(Arrays.toString(result));
代码的主要租户是:
noneMatch
),检查该元素是否等于该流中的任何元素。String[]
。使用Set
的另一种方法,再次使用流:
Set<String> setA = new HashSet<>(Arrays.asList(a));
Set<String> setB = new HashSet<>(Arrays.asList(b));
String[] setResult = setA.stream()
.filter((s) -> !setB.contains(s))
.toArray(String[]::new);
指出非Set代码的主要问题是在最坏的情况下它是二次时间。此代码利用Set#contains
的常量访问时间,并且应该在大约线性时间内运行。
答案 3 :(得分:3)
我会分三步处理:
a
但不是b
b
但不是a
例如:
Set<String> aSet = new HashSet<>(Arrays.asList(a));
Set<String> bSet = new HashSet<>(Arrays.asList(b));
Set<String> aNotB = new HashSet<>(aSet);
aNotB.removeAll(bSet);
Set<String> bNotA = new HashSet<>(bSet);
bNotA.removeAll(aSet);
Set<String> onlyOne = new HashSet<>(aNotB);
onlyOne.addAll(bNotA);
(Java 8中的流代码也可能使这个更简单......)
如果您不介意修改aSet
和bSet
,可以缩短代码,但我发现此版本更易于阅读。
答案 4 :(得分:2)
试试这个:
String a[]={"a","b","c","d"};
String b[]={"b","c"};
List aLst = new ArrayList(Arrays.asList(a));
List bLst = new ArrayList(Arrays.asList(b));
aLst.removeAll(bLst);
System.out.println(aLst);
答案 5 :(得分:0)
如果字符串只是英文字母(或小字母......甚至是ASCII),我宁愿使用boolean [] by char值而不是HashSets等来稍微改善性能。