Collection ohne Dubletten

sebastianb

Erfahrenes Mitglied
Hallo zusammen,

ich bin gerade an einem "Problem", wobei ich eher wieder glaube den Wald vor lauter Bäumen nicht zu sehen ;)

Also ich habe eine Collection, die mehrere Dubletten aufweist, was jedoch nicht sein soll. Also habe ich mir gedacht ich nehme einfach ein Set und das Problem wäre erledigt.

Das Dumme ist jetzt nur, dass die Objekte nicht identisch sind (== ist false), weshalb auch im Set Dupletten entstehen.
Leider habe ich auch weder die Möglichkeit equals oder hashcode zu überschreiben, um dieses Problem über diesen Weg in den Griff zu bekommen.

Kennt jemand also zufällig irgendeine Methode wie z.B.

Collection.removeDublets(Comparator c)

Da es sich in meinem Fall um Massendaten handelt, fände ich es sehr unschön mit Blick auf die Performance vor dem "add" über die Collection zu rattern.

Viele Grüße

Sebastian
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

2 Mögliche Lösungen (die etwas Speicher kosten) wären:
Java:
package de.tutorials;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class UniqueCollectionExample {
	public static void main(String[] args) {

		Collection<Item> items = new ArrayList<>();
		items.add(new Item(1));
		items.add(new Item(1));
		items.add(new Item(2));
		items.add(new Item(3));
		items.add(new Item(2));

		// Variante 1
		@SuppressWarnings("serial")
		Set<Item> set0 = new HashSet<Item>() {

			Set<Integer> uniqueValues = new HashSet<>();

			@Override
			public boolean add(Item e) {
				return uniqueValues.add(e.getUniqueCriteria()) && super.add(e);
			}
		};

		set0.addAll(items);
		System.out.println(set0);

		// Variante 2
		@SuppressWarnings("serial")
		Set<Item> set1 = new HashSet<Item>(items) {

			private Set<ItemWrapper> wrappers;

			@Override
			public boolean add(Item e) {
				return getMappers().add(new ItemWrapper(e));
			}

			@Override
			public Iterator<Item> iterator() {
				return newUnwrappingIterator();
			}
			
			@Override
			public int size() {
				return wrappers.size();
			}
			
			/*
			  contains / remove nicht unterstützt...
			 */

			private Iterator<Item> newUnwrappingIterator() {
				final Iterator<ItemWrapper> wrapperIter = getMappers().iterator();
				return new Iterator<UniqueCollectionExample.Item>() {
					@Override
					public boolean hasNext() {
						return wrapperIter.hasNext();
					}

					@Override
					public Item next() {
						return wrapperIter.next().getItem();
					}

					@Override
					public void remove() {
						wrapperIter.remove();
					}
				};
			}

			private Set<ItemWrapper> getMappers() {
				if (wrappers == null) {
					wrappers = new HashSet<>();
				}
				return wrappers;
			}

		};

		System.out.println(set1);

	}

	static class Item {
		private final int uniqueCriteria;

		public Item(int value) {
			this.uniqueCriteria = value;
		}

		public int getUniqueCriteria() {
			return uniqueCriteria;
		}

		@Override
		public String toString() {
			return String.valueOf(uniqueCriteria);
		}
	}

	static class ItemWrapper {
		private final Item item;

		public ItemWrapper(Item item) {
			this.item = item;
		}
		
		public Item getItem() {
			return item;
		}

		@Override
		public boolean equals(Object that) {
			return that instanceof ItemWrapper
					&& this.item.getUniqueCriteria() == ((ItemWrapper) that).item.getUniqueCriteria();
		}

		@Override
		public int hashCode() {
			return this.item.getUniqueCriteria();
		}

	}

}

Ausgabe:
Java:
[3, 2, 1]
[1, 2, 3]

Gruß Tom