@Override
  public ExampleSet apply(ExampleSet exampleSet) throws OperatorException {
    // creating kernel and settings from Parameters
    int k = Math.min(100, exampleSet.getAttributes().size() * 2);
    int size = exampleSet.size();
    switch (getParameterAsInt(PARAMETER_SAMPLE)) {
      case SAMPLE_ABSOLUTE:
        size = getParameterAsInt(PARAMETER_SAMPLE_SIZE);
        break;
      case SAMPLE_RELATIVE:
        size = (int) Math.round(exampleSet.size() * getParameterAsDouble(PARAMETER_SAMPLE_RATIO));
        break;
    }

    DistanceMeasure distanceMeasure = new EuclideanDistance();
    distanceMeasure.init(exampleSet);

    // finding farthest and nearest example to mean Vector
    double[] meanVector = getMeanVector(exampleSet);
    Candidate min = new Candidate(meanVector, Double.POSITIVE_INFINITY, 0);
    Candidate max = new Candidate(meanVector, Double.NEGATIVE_INFINITY, 0);
    int i = 0;
    for (Example example : exampleSet) {
      double[] exampleValues = getExampleValues(example);
      Candidate current =
          new Candidate(
              exampleValues,
              Math.abs(distanceMeasure.calculateDistance(meanVector, exampleValues)),
              i);
      if (current.compareTo(min) < 0) {
        min = current;
      }
      if (current.compareTo(max) > 0) {
        max = current;
      }
      i++;
    }
    ArrayList<Candidate> recentlySelected = new ArrayList<Candidate>(10);
    int[] partition = new int[exampleSet.size()];
    int numberOfSelectedExamples = 2;
    recentlySelected.add(min);
    recentlySelected.add(max);
    partition[min.getExampleIndex()] = 1;
    partition[max.getExampleIndex()] = 1;
    double[] minimalDistances = new double[exampleSet.size()];
    Arrays.fill(minimalDistances, Double.POSITIVE_INFINITY);

    // running now through examples, checking for smallest distance to one of the candidates
    while (numberOfSelectedExamples < size) {
      TreeSet<Candidate> candidates = new TreeSet<Candidate>();

      i = 0;
      // check distance only for candidates recently selected.
      for (Example example : exampleSet) {
        // if example not has been selected allready
        if (partition[i] == 0) {
          double[] exampleValues = getExampleValues(example);
          for (Candidate candidate : recentlySelected) {
            minimalDistances[i] =
                Math.min(
                    minimalDistances[i],
                    Math.abs(
                        distanceMeasure.calculateDistance(exampleValues, candidate.getValues())));
          }
          Candidate newCandidate = new Candidate(exampleValues, minimalDistances[i], i);
          candidates.add(newCandidate);
          if (candidates.size() > k) {
            Iterator<Candidate> iterator = candidates.iterator();
            iterator.next();
            iterator.remove();
          }
        }
        i++;
      }
      // clearing recently selected since now new ones will be selected
      recentlySelected.clear();

      // now running in descending order through candidates and adding to selected
      // IM: descendingIterator() is not available in Java versions less than 6 !!!
      // IM: Bad workaround for now by adding all candidates into a list and using a listIterator()
      // and hasPrevious...
      /*
      Iterator<Candidate> descendingIterator = candidates.descendingIterator();
      while (descendingIterator.hasNext() && numberOfSelectedExamples < desiredNumber) {
      	Candidate candidate = descendingIterator.next();
       */

      List<Candidate> reverseCandidateList = new LinkedList<Candidate>();
      Iterator<Candidate> it = candidates.iterator();
      while (it.hasNext()) {
        reverseCandidateList.add(it.next());
      }

      ListIterator<Candidate> lit =
          reverseCandidateList.listIterator(reverseCandidateList.size() - 1);
      while (lit.hasPrevious()) {
        Candidate candidate = lit.previous();
        // IM: end of workaround

        boolean existSmallerDistance = false;
        Iterator<Candidate> addedIterator = recentlySelected.iterator();
        // test if a distance to recently selected is smaller than previously calculated minimal
        // distance
        // if one exists: This is not selected
        while (addedIterator.hasNext()) {
          double distance =
              Math.abs(
                  distanceMeasure.calculateDistance(
                      addedIterator.next().getValues(), candidate.getValues()));
          existSmallerDistance = existSmallerDistance || distance < candidate.getDistance();
        }
        if (!existSmallerDistance) {
          recentlySelected.add(candidate);
          partition[candidate.getExampleIndex()] = 1;
          numberOfSelectedExamples++;
        } else break;
      }
    }

    // building new exampleSet containing only Examples with indices in selectedExamples

    SplittedExampleSet sample = new SplittedExampleSet(exampleSet, new Partition(partition, 2));
    sample.selectSingleSubset(1);
    return sample;
  }
 public int compareTo(Candidate o) {
   return Double.compare(this.distance, o.getDistance());
 }