![](/img/trans.png)
[英]Removing duplicates from array without using any collection api of java
[英]Java: Equalator? (removing duplicates from a collection of objects)
我有一堆类Puzzle
。 我重写了equals()
和hashCode()
。 当需要向用户展示解决方案时,我想过滤掉所有“相似”的难题(按照我定义的标准),因此用户只能看到其中的一个。
相似性是可传递的。
例:
Result of computations:
A (similar to A)
B (similar to C)
C
D
在这种情况下,只会向用户显示A或D以及B或C-但不会显示两个类似的拼图。 两个类似的难题同样有效。 重要的是不要同时向用户显示它们。
为此,我想使用禁止重复的ADT。 但是,我不想更改equals()
和hashCode()
方法来返回有关相似性的值。 在这种情况下是否可以使用某些Equalator
(例如Comparator
? 还是我应该采取另一种方式?
我正在上的课是一个拼图,它保持字母网格。 (如拼字游戏。)如果“拼图”包含相同的单词,但方向不同,则认为它是相似的。 因此,以下内容令人困惑:
(2, 2): A
(2, 1): C
(2, 0): T
将类似于:
(1, 2): A
(1, 1): C
(1, 0): T
我将使用一个包装器类来相应地覆盖equals
和hashCode
。
private static class Wrapper {
public static final Puzzle puzzle;
public Wrapper(Puzzle puzzle) {
this.puzzle = puzzle;
}
@Override
public boolean equals(Object object) {
// ...
}
@Override
public int hashCode() {
// ...
}
}
然后将所有谜题包起来,将它们放在地图中,然后再次将它们取出…
public Collection<Collection<Puzzle>> method(Collection<Puzzles> puzzles) {
Map<Wrapper,<Collection<Puzzle>> map = new HashMap<Wrapper,<Collection<Puzzle>>();
for (Puzzle each: puzzles) {
Wrapper wrapper = new Wrapper(each);
Collection<Puzzle> coll = map.get(wrapper);
if (coll == null) map.put(wrapper, coll = new ArrayList<Puzzle>());
coll.add(puzzle);
}
return map.values();
}
好的,您可以使用一种方法来测量对象之间的相似性。 这意味着它们形成一个度量空间 。
问题是,您的空间还是像普通的三维空间还是整数之类的欧几里德空间 ? 如果是这样,则可以使用二进制空间分区 ,无论您拥有多少维。
(问题基本上是:您的对象和n维实数向量之间是否存在同态?如果是,那么您可以使用技术来测量n维空间中点的紧密度。)
a euclidean space then you've got a bigger problem. 现在,如果它欧几里德空间,那么您将面临更大的问题。 程序员可能最熟悉的非欧几里德空间的一个示例是字符串之间的Levenshtein距离 。
of any algorithms that would do that without O(n 2 ) time. 如果您的问题类似于查看字符串与已存在的字符串列表的相似程度,那么我不没有O(n 2 )时间就能做到的算法。 也许那里有一些。
但是另一个重要的问题是:您有多少时间? 有多少个物体? 如果您有时间,或者您的数据集足够小,以至于O(n 2 )算法是可行的,那么您仅需遍历对象列表以查看其是否低于某个阈值。 如果是这样,请拒绝它。
只需重载AbstractCollection并替换Add函数即可。 使用ArrayList或其他。 您的代码看起来像这样
class SimilarityRejector<T> extends AbstractCollection<T>{
ArrayList<T> base;
double threshold;
public SimilarityRejector(double threshold){
base = new ArrayList<T>();
this.threshold = threshold;
}
public void add(T t){
boolean failed = false;
for(T compare : base){
if(similarityComparison(t,compare) < threshold) faled = true;
}
if(!failed) base.add(t);
}
public Iterator<T> iterator() {
return base.iterator();
}
public int size() {
return base.size();
}
}
等等。显然,T必须是您可以对其进行比较的某个类的子类。 如果您具有欧几里德度量标准,则可以使用空间分区,而不要遍历其他所有项目。
恕我直言,最优雅的方式是由Gili(带有自定义比较器的TreeSet)描述的。
但是,如果您想自己做,这似乎是最简单,最清晰的解决方案:
/**
* Distinct input list values (cuts duplications)
* @param items items to process
* @param comparator comparator to recognize equal items
* @return new collection with unique values
*/
public static <T> Collection<T> distinctItems(List<T> items, Comparator<T> comparator) {
List<T> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
T item = items.get(i);
boolean exists = false;
for (int j = 0; j < result.size(); j++) {
if (comparator.compare(result.get(j), item) == 0) {
exists = true;
break;
}
}
if (!exists) {
result.add(item);
}
}
return result;
}
通常,“相似性”不是传递关系。 因此,第一步是从等价而非相似的角度来考虑。 等价是自反的,对称的和可传递的。
此处的简单方法是定义一个难题包装程序,该程序的equals()和hashCode()方法是根据所讨论的等效关系实现的。
一旦有了,就将包装的对象放到java.util.Set中,并过滤掉重复的对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.