code: @MainThread
      public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,
              @NonNull final Function<X, Y> func) {
          final MediatorLiveData<Y> result = new MediatorLiveData<>();
          result.addSource(source, new Observer<X>() {
              @Override
              public void onChanged(@Nullable X x) {
                  result.setValue(func.apply(x));
              }
          });
          return result;
      }
docs: Applies the given function on the main thread to each value emitted by {@code source}
  LiveData and returns LiveData, which emits resulting values.
  <p>
  The given function {@code func} will be executed on the main thread.
  <p>
  Suppose that you have a LiveData, named {@code userLiveData}, that contains user data and you
  need to display the user name, created by concatenating the first and the last
  name of the user. You can define a function that handles the name creation, that will be
  applied to every value emitted by {@code useLiveData}.
  
  <pre>
  LiveData&lt;User&gt; userLiveData = ...;
  LiveData&lt;String&gt; userName = Transformations.map(userLiveData, user -&gt; {
  return user.firstName + " " + user.lastName
  });
  </pre>
  
  @param <X>    a type of {@code source} LiveData
  @param <Y>    a type of resulting LiveData.
  @param source a {@code LiveData} to listen to
  @param func   a function to apply
  @return a LiveData which emits resulting values