Class Converter<A,​B>

  • All Implemented Interfaces:
    Function<A,​B>, Function<A,​B>

    @GwtCompatible
    public abstract class Converter<A,​B>
    extends Object
    implements Function<A,​B>
    A function from A to B with an associated reverse function from B to A; used for converting back and forth between different representations of the same information.

    Invertibility

    The reverse operation may be a strict inverse (meaning that converter.reverse().convert(converter.convert(a)).equals(a) is always true). However, it is very common (perhaps more common) for round-trip conversion to be lossy. Consider an example round-trip using Doubles.stringConverter():

    1. stringConverter().convert("1.00") returns the Double value 1.0
    2. stringConverter().reverse().convert(1.0) returns the string "1.0" -- not the same string ("1.00") we started with

    Note that it should still be the case that the round-tripped and original objects are similar.

    Nullability

    A converter always converts null to null and non-null references to non-null references. It would not make sense to consider null and a non-null reference to be "different representations of the same information", since one is distinguishable from missing information and the other is not. The convert(A) method handles this null behavior for all converters; implementations of doForward(A) and doBackward(B) are guaranteed to never be passed null, and must never return null.

    Common ways to use

    Getting a converter:

    • Use a provided converter implementation, such as Enums.stringConverter(java.lang.Class<T>), Ints.stringConverter or the reverse views of these.
    • Convert between specific preset values using Maps.asConverter. For example, use this to create a "fake" converter for a unit test. It is unnecessary (and confusing) to mock the Converter type using a mocking framework.
    • Extend this class and implement its doForward(A) and doBackward(B) methods.
    • Java 8+ users: you may prefer to pass two lambda expressions or method references to the from factory method.

    Using a converter:

    • Convert one instance in the "forward" direction using converter.convert(a).
    • Convert multiple instances "forward" using converter.convertAll(as).
    • Convert in the "backward" direction using converter.reverse().convert(b) or converter.reverse().convertAll(bs).
    • Use converter or converter.reverse() anywhere a Function is accepted (for example Stream.map).
    • Do not call doForward(A) or doBackward(B) directly; these exist only to be overridden.

    Example

       return new Converter<Integer, String>() {
         protected String doForward(Integer i) {
           return Integer.toHexString(i);
         }
    
         protected Integer doBackward(String s) {
           return parseUnsignedInt(s, 16);
         }
       };

    An alternative using Java 8:

    
     return Converter.from(
         Integer::toHexString,
         s -> parseUnsignedInt(s, 16));
     
    Since:
    16.0
    Author:
    Mike Ward, Kurt Alfred Kluever, Gregory Kick
    • Constructor Detail

      • Converter

        protected Converter()
        Constructor for use by subclasses.
    • Method Detail

      • doForward

        @ForOverride
        protected abstract B doForward​(A a)
        Returns a representation of a as an instance of type B. If a cannot be converted, an unchecked exception (such as IllegalArgumentException) should be thrown.
        Parameters:
        a - the instance to convert; will never be null
        Returns:
        the converted instance; must not be null
      • doBackward

        @ForOverride
        protected abstract A doBackward​(B b)
        Returns a representation of b as an instance of type A. If b cannot be converted, an unchecked exception (such as IllegalArgumentException) should be thrown.
        Parameters:
        b - the instance to convert; will never be null
        Returns:
        the converted instance; must not be null
        Throws:
        UnsupportedOperationException - if backward conversion is not implemented; this should be very rare. Note that if backward conversion is not only unimplemented but unimplementable (for example, consider a Converter<Chicken, ChickenNugget>), then this is not logically a Converter at all, and should just implement Function.
      • convert

        public final @Nullable B convert​(@Nullable A a)
        Returns a representation of a as an instance of type B.
        Returns:
        the converted value; is null if and only if a is null
      • convertAll

        public Iterable<BconvertAll​(Iterable<? extends A> fromIterable)
        Returns an iterable that applies convert to each element of fromIterable. The conversion is done lazily.

        The returned iterable's iterator supports remove() if the input iterator does. After a successful remove() call, fromIterable no longer contains the corresponding element.

      • reverse

        @CheckReturnValue
        public Converter<B,​Areverse()
        Returns the reversed view of this converter, which converts this.convert(a) back to a value roughly equivalent to a.

        The returned converter is serializable if this converter is.

        Note: you should not override this method. It is non-final for legacy reasons.

      • andThen

        public final <C> Converter<A,​C> andThen​(Converter<B,​C> secondConverter)
        Returns a converter whose convert method applies secondConverter to the result of this converter. Its reverse method applies the converters in reverse order.

        The returned converter is serializable if this converter and secondConverter are.

      • equals

        public boolean equals​(@Nullable Object object)
        Indicates whether another object is equal to this converter.

        Most implementations will have no reason to override the behavior of Object.equals(java.lang.Object). However, an implementation may also choose to return true whenever object is a Converter that it considers interchangeable with this one. "Interchangeable" typically means that Objects.equal(this.convert(a), that.convert(a)) is true for all a of type A (and similarly for reverse). Note that a false result from this method does not imply that the converters are known not to be interchangeable.

        Specified by:
        equals in interface Function<A,​B>
        Overrides:
        equals in class Object
      • from

        public static <A,​B> Converter<A,​B> from​(Function<? super A,​? extends B> forwardFunction,
                                                            Function<? super B,​? extends A> backwardFunction)
        Returns a converter based on separate forward and backward functions. This is useful if the function instances already exist, or so that you can supply lambda expressions. If those circumstances don't apply, you probably don't need to use this; subclass Converter and implement its doForward(A) and doBackward(B) methods directly.

        These functions will never be passed null and must not under any circumstances return null. If a value cannot be converted, the function should throw an unchecked exception (typically, but not necessarily, IllegalArgumentException).

        The returned converter is serializable if both provided functions are.

        Since:
        17.0
      • identity

        public static <T> Converter<T,​T> identity()
        Returns a serializable converter that always converts or reverses an object to itself.