A method that generates a Comparator using lambda expression Given below is an exercise from the book *Java SE 8 for the Really Impatient( by Cay S. Horstmann:


  Write a method that generates a Comparator that can be normal or
  reversed, case-sensitive or case-insensitive, space-sensitive or
  space-insensitive, or any combination thereof. Your method should
  return a lambda expression.


Is there a better (efficient, elegant) way to do it than below?

public static final int COMPARE_REVERSED = 0x01;
public static final int COMPARE_CASE_INSENSITIVE = 0x02;
public static final int COMPARE_SPACE_INSENSITIVE = 0x04;

public static Comparator&lt;String&gt; getComparator(int flags) {

    return (s1, s2) -&gt; {
        if (has(flags, COMPARE_REVERSED)) {
            String temp = s1;
            s1 = s2;
            s2 = temp;
        }
        if (has(flags, COMPARE_SPACE_INSENSITIVE)) {
            s1 = s1.replaceAll("\\s", "");
            s2 = s2.replaceAll("\\s", "");
        }
        if (has(flags, COMPARE_CASE_INSENSITIVE)) {
            return s1.compareToIgnoreCase(s2);
        }
        return s1.compareTo(s2);
    };
}

public static boolean has(int flags, int FLAG) {
    return (flags &amp; FLAG) != 0;
}
This seems as efficient as it gets, to me.

In terms of elegance, Joshua Bloch (in Effective Java) recommends to stop using bit fields, use EnumSet instead.

The first step is to change your bit fields to an enum:

public enum Mode {
    COMPARE_REVERSED,
    COMPARE_CASE_INSENSITIVE,
    COMPARE_SPACE_INSENSITIVE
}


Next, change your method to take a Set instead of an int:

public static Comparator&lt;String&gt; getComparator(Set&lt;Mode&gt; flags) {
    return (s1, s2) -&gt; {
        if (flags.contains(Mode.COMPARE_REVERSED)) {
            String temp = s1;
            s1 = s2;
            s2 = temp;
        }
        if (flags.contains(Mode.COMPARE_SPACE_INSENSITIVE)) {
            s1 = s1.replaceAll("\\s", "");
            s2 = s2.replaceAll("\\s", "");
        }
        if (flags.contains(Mode.COMPARE_CASE_INSENSITIVE)) {
            return s1.compareToIgnoreCase(s2);
        }
        return s1.compareTo(s2);
    };
}


You could call this method with any Set, but it will be best to call with an EnumSet, for example:

getComparator(EnumSet.of(Mode.COMPARE_CASE_INSENSITIVE, Mode.COMPARE_SPACE_INSENSITIVE));


Why is this better?


You don't need to worry about setting the bit fields correctly to be mutually exclusive
You don't need the has method anymore, now you can use simple Set.contains
You don't need the ... | ... bit operations anymore, EnumSet.of(...) is simple and clean


In short (quoted from the book):


  No more bit twiddling, EnumSet does all the hard work for you.


I would also add a convenience method for the case of no flags:

public static Comparator&lt;String&gt; getComparator() {
    return getComparator(Collections.&lt;Mode&gt;emptySet());
}


And of course, a bunch of unit tests, for example:

@Test
public void testNormalComparator() {
    Comparator&lt;String&gt; comparator = ComparatorGenerator.getComparator();
    assertNotEquals(0, comparator.compare("hello", "Hello"));
    assertEquals(0, comparator.compare("hello", "hello"));
}

@Test
public void testCaseInsensitiveComparator() {
    Comparator&lt;String&gt; comparator = ComparatorGenerator.getComparator(EnumSet.of(ComparatorGenerator.Mode.COMPARE_CASE_INSENSITIVE));
    assertNotEquals(0, comparator.compare("hello", "xHello"));
    assertEquals(0, comparator.compare("hello", "Hello"));
    assertEquals(0, comparator.compare("hello", "hello"));
}

@Test
public void testReversedComparator() {
    Comparator&lt;String&gt; comparator1 = ComparatorGenerator.getComparator();
    assertEquals(-1, comparator1.compare("hello1", "hello2"));
    Comparator&lt;String&gt; comparator2 = ComparatorGenerator.getComparator(EnumSet.of(ComparatorGenerator.Mode.COMPARE_REVERSED));
    assertEquals(1, comparator2.compare("hello1", "hello2"));
}

@Test
public void testCaseAndSpaceInsensitiveComparator() {
    Comparator&lt;String&gt; comparator = ComparatorGenerator.getComparator(EnumSet.of(ComparatorGenerator.Mode.COMPARE_CASE_INSENSITIVE, ComparatorGenerator.Mode.COMPARE_SPACE_INSENSITIVE));
    assertNotEquals(0, comparator.compare("hello there", "x hello there"));
    assertEquals(0, comparator.compare("HELLO there", "h e llo there"));
}