Code Pretty Print Script

Friday, November 8, 2013

Reverse the Polarity

Sometimes, you need to reverse the polarity of a Comparator and it should be smart so that you can reverse the Comparator over and over again without consuming more resources.

/*
 * Copyright © 2013 - Elliott Frisch
 * 
 * THIS SOFTWARE IS PROVIDED UNDER THE CREATIVE COMMONS
 * LICENSE 3.0 "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
 * A PARTICULAR PURPOSE.
 * 
 * To use this software you must agree to the complete
 * license terms available at:
 * http://creativecommons.org/licenses/by/3.0/us/deed.en_US
 * 
 * It is the intent of the author(s) that you may use or
 * modify this software for any purpose (including your own
 * commercial gain) provided that this notice remains in its
 * entirety.
 * 
 * Created by Elliott Frisch - www.frischcode.com
 */
package com.frischcode.util;

import java.util.Arrays;
import java.util.Comparator;

/**
 * <b>Rationale:</b> Frequently you need to <a href=
 * "http://tinyurl.com/2dr3buq">reverse the polarity</a> of
 * a Comparator (e.g. from Ascending to Descending or
 * vice-versa). Implemented with two <a href=
 * "http://tinyurl.com/65d2m">Design Patterns</a>;
 * <ol>
 * <li><a href="http://tinyurl.com/r6gcx">Decorator</a></li>
 * <li>
 * <a href="http://tinyurl.com/muw5h">Factory method</a></li>
 * </ol>
 * <b>NOTE:</b> The Factory method pattern is used to
 * prevent nesting.
 * 
 * @author Elliott Frisch
 */
public class ReverseComparator<T> implements
    Comparator<T> {
  /**
   * Performs "lite" Construction assistance for reversing a
   * Comparator while preventing "deep" nesting. By design,
   * the reverse of the reverse is a reference to the
   * original Comparator.
   * 
   * @param comparator
   *          The comparator to reverse.
   * @return A comparator that behaves in the opposite
   *         manner to that initially provided.
   */
  public static <R> Comparator<R> reverseComparator(
      final Comparator<R> comparator) {
    if (comparator == null) {
      return null;
    } else if (comparator instanceof ReverseComparator) {
      return ((ReverseComparator<R>) comparator).comparator;
    }
    return new ReverseComparator<R>(comparator);
  }

  /**
   * Provide a basic demonstration.
   * 
   * @see com.frischcode.util.ComparableComparator
   */
  public static void main(String[] args) {
    String[] array = new String[] { "Hello", "World",
        "Goodbye", "It's" };
    // java.lang.String is Comparable.
    // Help! I have a Comparable but I need a Comparator...
    // http://tinyurl.com/lg5pyvy
    Comparator<String> comp = new ComparableComparator<String>();
    Comparator<String> comp2 = reverseComparator(comp);
    Comparator<String> comp3 = reverseComparator(comp2);
    if (comp == comp3) {
      System.out.println("The Reverse Reverse "
          + "Comparator refers to the initial "
          + "Comparator");
    } else {
      System.err.println("The Reverse Reverse "
          + "Comparator DOES NOT refer to "
          + "the initial Comparator");
    }
    printArray("Initial", array);
    Arrays.sort(array, comp);
    printArray("Normal Sort", array);
    Arrays.sort(array, comp2);
    printArray("Reverse Sort", array);
  }

  // Outputs an array.
  private static void printArray(final String state,
      final String[] array) {
    final StringBuilder sb = new StringBuilder(state);
    sb.append(" Array = [");
    for (int i = 0; i < array.length; ++i) {
      if (i != 0) {
        sb.append(", ");
      }
      sb.append(array[i]);
    }
    sb.append("]");
    System.out.println(sb.toString());
  }

  /**
   * Do the opposite of our decorated Comparator.
   * 
   * @see java.util.Comparator#compare(java.lang.Object,
   *      java.lang.Object)
   */
  @Override
  public int compare(final T o1, final T o2) {
    return (comparator != null) ? comparator.compare(
        o2, o1) : 0;
  }

  // To prevent nested instantiation.
  private ReverseComparator(
      final Comparator<T> comparator) {
    this.comparator = comparator;
  }

  private final Comparator<T> comparator;
}