In this program, we prevent duplicate elements in loadedAnimals by overriding the equals and hashCode method in AnimalPair or by preventing the calling code the have duplicates in candidate collections.
import java.util.*;
public class Animals {
Ark ark;
Species species;
Gender gender;
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
// animals confined to method, don't let them escape!
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
public static void main(String...args) {
Animals animals = new Animals();
animals.ark = animals.new Ark();
Thread helper = new Thread(new Runnable(){
@Override
public void run() {
Collection<Animal> candidates2 = new TreeSet<Animal>(animals.new SpeciesGenderComparator());
for(Species s: Species.values()) {
for(Gender g: Gender.values()) {
if(s.toString().charAt(0) <= 'H') {
candidates2.add(animals.new Animal(s, g));
}
}
}
System.out.println(animals.loadTheArk(candidates2) + " pairs of animals loaded");
System.out.println(Species.UNICORN + " is on the ark? " + animals.ark.hasAminal(Species.UNICORN));
System.out.println(Species.AARDVARK + " is on the ark? " + animals.ark.hasAminal(Species.AARDVARK));
}});
helper.start();
Collection<Animal> candidates = new TreeSet<Animal>(animals.new SpeciesGenderComparator());
for(Species s: Species.values()) {
for(Gender g: Gender.values()) {
if(s.toString().charAt(0) > 'H') {
candidates.add(animals.new Animal(s, g));
}
}
}
System.out.println(animals.loadTheArk(candidates) + " pairs of animals loaded");
System.out.println(Species.UNICORN + " is on the ark? " + animals.ark.hasAminal(Species.UNICORN));
System.out.println(Species.AARDVARK + " is on the ark? " + animals.ark.hasAminal(Species.AARDVARK));
}
class Animal {
Species species;
Gender gender;
public Animal(Species species, Gender gender) {
this.species = species;
this.gender = gender;
}
public boolean isPotentialMate(Animal other) {
return species == other.species && gender != other.gender;
}
}
enum Species {
AARDVARK, BENGAL_TIGER, CARIBOU, DINGO, ELEPHANT, FROG, GNU, HYENA,
IGUANA, JAGUAR, KIWI, LEOPARD, MASTADON, NEWT, OCTOPUS,
PIRANHA, QUETZAL, RHINOCEROS, SALAMANDER, THREE_TOED_SLOTH,
UNICORN, VIPER, WEREWOLF, XANTHUS_HUMMINBIRD, YAK, ZEBRA
}
enum Gender {
MALE, FEMALE
}
class AnimalPair {
//logical equality?
private final Animal one, two;
public AnimalPair(Animal one, Animal two) {
this.one = one;
this.two = two;
}
}
class SpeciesGenderComparator implements Comparator<Animal> {
public int compare(Animal one, Animal two) {
int speciesCompare = one.species.compareTo(two.species);
return (speciesCompare != 0)
? speciesCompare
: one.gender.compareTo(two.gender);
}
}
class Ark {
private final Set<AnimalPair> loadedAnimals = new HashSet<AnimalPair>();
public synchronized void load(AnimalPair pair) {
loadedAnimals.add(pair);
}
public synchronized boolean hasAminal(Species s) {
for (AnimalPair ap : loadedAnimals) {
if (ap.one.species.compareTo(s) == 0) {
return true;
}
}
return false;
}
}
}