[英]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.