This method, as I know, memorizes (caches) the value of supplier that passed as the parameter. As I understand It behaves like singleton pattern. Can anyone explain how it works?
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier)
{
final List<T> memoryList= new ArrayList<>();
return () -> {
if (memoryList.isEmpty()) {
memoryList.add(valueSupplier.get());
}
return memoryList.get(0);
};
}
Usage like this:
Supplier<SomeClass> cachedValue = memoize(() -> someClassObject.getSomeValueToBeCached());
cachedValue.get().doMethod();
Ok, so let's rewrite the code in small steps towards more old-style, verbose Java.
Maybe that makes it simpler to understand.
First step: get rid of the lambda:
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier)
{
final List<T> memoryList= new ArrayList<>();
return new Supplier<T>() {
#Override
public T get() {
if (memoryList.isEmpty()) {
memoryList.add(valueSupplier.get());
}
return memoryList.get(0);
}
};
}
Next step: extract the anonymous inner class into a standalone class.
While the anonymous class had access to the local variables of its containing method (memoryList), a "normal" class has not, so we're moving the list into the caching supplier.
class CachingSupplier<T> implements Supplier<T> {
final List<T> memoryList= new ArrayList<>();
private Supplier<T> originalSupplier;
public CachingSupplier(Supplier<T> originalSupplier) {
this.originalSupplier = originalSupplier;
}
#Override
public T get() {
if (memoryList.isEmpty()) {
memoryList.add(originalSupplier.get());
}
return memoryList.get(0);
}
}
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier) {
return new CachingSupplier<>(valueSupplier);
}
Finally, let's replace the ArrayList by a simple reference.
class CachingSupplier<T> implements Supplier<T> {
private T cachedValue;
private Supplier<T> originalSupplier;
public CachingSupplier(Supplier<T> originalSupplier) {
this.originalSupplier = originalSupplier;
}
#Override
public T get() {
if (cachedValue == null) {
cachedValue = originalSupplier.get();
}
return cachedValue;
}
}
public static <T> Supplier<T> memoize(final Supplier<? extends T> valueSupplier) {
return new CachingSupplier<>(valueSupplier);
}
Maybe that's easier to understand. If you are still unclear about something, just ask in a comment
and I'll try to explain it.
How about this?
public static <T> Supplier<T> memoize(final Supplier<? extends T> factory) {
final List<T> cache = new ArrayList<>();
return () -> {
// v--- check the value is cached?
if (cache.isEmpty()) {
// v--- return the value created by factory
cache.add(factory.get());
// ^--- adding the value into the cache
}
return cache.get(0);
// ^--- return the cached value
};
}
Usage
Supplier<String> factory = ()-> new String("foo");
assert factory.get() == factory.get(); // return false;
assert memoize(factory).get() == memoize(factory).get(); //return false;
// v--- storing the memoized factory for using as further
Supplier<String> memoized = memoize(original);
assert memoized.get() == memoized.get(); // return true.
// ^--- they are the same.
Related
I am currently learning about the functionalities of the Optional class, and I am trying to build a simplified version of the Optional class. I was able to code ifPresent(), filter(), of(), map() and so on. However, I am currently stuck with the implementing or().
I know that or() have the signature Optional<T> or(Supplier<? extends Optional<? extends T>> supplier). However, my implementation assumed that I can access the contents of the Optional. As show below:
class Optional<T> {
private final T item;
...
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if (this.item == null) {
T item = supplier.get().item;
return Maybe.<T>of(item);
} else {
return this;
}
}
}
As you can see, T item = supplier.get().item would throw an error saying that .item is inaccessible due to it being private. How am I able to access the item without causing this error?
First, you need to recall that you can not access a private field through an instance of a subtype, even though assigning the subtype reference to a variable of the current type, which allows the access, is possible without cast.
So if you have
public class ClassWithPrivateField {
private String field;
static class Subclass extends ClassWithPrivateField {}
void someMethod(Subclass obj) {
String s = obj.field; // does not work, you can't access field through Subclass
}
}
you may write
public class ClassWithPrivateField {
private String field;
static class Subclass extends ClassWithPrivateField {}
void someMethod(Subclass obj) {
ClassWithPrivateField withBroaderType = obj; // always works
String s = withBroaderType.field; // now, no problem to access field
}
}
Now to your more complicated generic variant. If you have
public class Optional<T> {
private final T item;
private Optional(T t) {
item = t;
}
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if(this.item == null) {
T item = supplier.get().item;
return Optional.of(item);
}
else return this;
}
private static <T> Optional<T> of(T item2) {
return new Optional<>(item2);
}
}
the access to item is rejected by the compiler because the type returned by the supplier is ? extends Optional<? extends T> which is a subtype of Optional<? extends T>, just the same way as Subclass is a subtype of ClassWithPrivateField.
You can fix the issue the same way, by introducing a variable:
public class Optional<T> {
private final T item;
private Optional(T t) {
item = t;
}
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if(this.item == null) {
Optional<? extends T> optional = supplier.get(); // valid assignment
T item = optional.item; // valid access
return Optional.of(item);
}
else return this;
}
private static <T> Optional<T> of(T item2) {
return new Optional<>(item2);
}
}
Alternatively, you could insert a type cast to Optional<? extends T> like
T item = ((Optional<? extends T>)supplier.get()).item;
but I would prefer the variant with a variable as it immediately shows to the reader that the assignment (without a cast) is a valid type transition which can never fail. The type cast can not fail either and is a no-op at runtime, but its syntax is indistinguishable from type casts performing a runtime check that could fail.
You just need to replace
T item = supplier.get().item;
return Maybe.<T>of(item);
with
return (Optional<T>)supplier.get();
I have an interface:
public interface ITransformer<S,T>{
public void transform(S source,T target);
default String getTransformerName(){
Class<S> s;
Class<T> t;
return s.getName() + t.getName(); //*********
}
}
the error message the starred line:
The local variable s may not have been initialized
The local variable t may not have been initialized
I would like to use this method to return a string with [S.classname][T.classname] . Please let me know how to achieve this or is this impossible to do at interface ?
Update: Jan 12
My purpose of doing this is due to the fact that this class will be in framework and I want to reduce the human error as much as possible.. I am changing the code as follows:
public interface ITransformer<S,T>{
public void transform(S source,T target);
public FieldEntry<S, T> getTransformerName();
}
public class FieldEntry<S,T> implements Comparable<FieldEntry> {
private Class<S> s;
private Class<T> t;
public FieldEntry(Class<S> s,Class<T> t){
this.s = s;
this.t = t;
}
public String getEntryName(){
return s.getName() + t.getName();
}
#Override
public int compareTo(FieldEntry entry) {
if(entry == null) throw new IllegalArgumentException("The argument to compare cannot be null!");
return entry.getEntryName().compareTo(this.getEntryName());
}
}
In order to demonstrate why this can’t work, you may change your class to
public interface ITransformer<S,T>{
public void transform(S source,T target);
static <In,Out> ITransformer<In,Out> noOp() {
return (source,target) -> {};
}
static void main(String... arg) {
ITransformer<String,Integer> t1 = noOp();
ITransformer<Long,Thread> t2 = noOp();
System.out.println(t1 == (Object)t2);
}
}
Running this will print true. In other words, both functions are represented by the same instances, so there can’t be and property allowing to recognize their different type.
Generally, when two functions (lambda expressions or method references) exhibit the same behavior, a JVM may represent them by the same implementation type or even the same instance.
Even for non-interface classes, this doesn’t work due to Type Erasure. It only works when you have a reifiable (i.e. non-generic) type extending or implementing a generic type.
It's a little bit dangerous and I wouldn't used this in production (because you should cover in your code all possible use cases of your interface), but you can use reflection for it:
public interface ITransformer<S, T> {
public void transform(S source, T target);
default String getTransformerName() {
Type[] genericInterfaces = this.getClass().getGenericInterfaces();
ParameterizedType parameterizedType = null;
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType paramInterface = (ParameterizedType) genericInterface;
if (paramInterface.getRawType().equals(ITransformer.class)) {
parameterizedType = paramInterface;
break;
}
}
}
if (parameterizedType == null) {
throw new IllegalStateException("!");
}
return parameterizedType.getActualTypeArguments()[0].getTypeName() + parameterizedType.getActualTypeArguments()[1].getTypeName();
}
}
public class StringToIntegerTransfomer implements ITransformer<String, Integer> {
#Override
public void transform(String source, Integer target) {
}
}
public interface StringToNumberTransfomer<T extends Number> extends ITransformer<String, T> {
}
public class StringToLongTransfomer implements StringToNumberTransfomer<Long>, ITransformer<String, Long> {
#Override
public void transform(String source, Long target) {
}
}
#Test
public void test() {
ITransformer<String, Integer> intTransformer = new StringToIntegerTransfomer();
ITransformer<String, Long> longTransformer = new StringToLongTransfomer();
ITransformer<String, String> stringTransformer = new ITransformer<String, String>() {
#Override
public void transform(String source, String target) {
}
};
ITransformer<String, Double> doubleTransformer = new StringToNumberTransfomer<Double>() {
#Override
public void transform(String source, Double target) {
}
};
System.out.println(String.format("intTransformer: %s", intTransformer.getTransformerName()));
System.out.println(String.format("longTransformer: %s", longTransformer.getTransformerName()));
System.out.println(String.format("stringTransformer: %s", stringTransformer.getTransformerName()));
System.out.println(String.format("doubleTransformer: %s", doubleTransformer.getTransformerName()));
}
Output for this snippet:
intTransformer: java.lang.Stringjava.lang.Integer
longTransformer: java.lang.Stringjava.lang.Long
stringTransformer: java.lang.Stringjava.lang.String
java.lang.IllegalStateException: !
This code has one restriction, you should say implements ITransformer<S, T> for all implementations of ITransformer. That why I have got IllegalStateException for this line ITransformer<String, Double> doubleTransformer = new StringToNumberTransfomer<Double>(). But you can improve this code.
Better option is to use some base implementation of interface and pass source and target classes into constructor:
public interface ITransformer<S, T> {
void transform(S source, T target);
String getTransformerName();
}
public abstract class BaseITransformer<S, T> implements ITransformer<S, T> {
private final Class<S> sourceClass;
private final Class<T> targetClass;
public BaseITransformer(Class<S> sourceClass, Class<T> targetClass) {
this.sourceClass = sourceClass;
this.targetClass = targetClass;
}
public String getTransformerName() {
return sourceClass.getName() + targetClass.getName();
}
}
In Java it is impossible to get a Class<S>, unless you already know which class S is, or something else that knows which class S is gives you one.
I built a simple document store, there are entities that have fields of different types, I have a Float, Int and String type. The entity contains an array list of values, if someone updates the schema of the entity I would like to be able to try to convert the values to the new type.
public interface FieldType<T> {
ArrayList<T> values;
}
public class FloatField implements FieldType<Float> {
}
public class StringField implements FieldType<String> {
}
I have thought about using a abstract class with methods as below
public abstract class Field<T> implements FieldType<T> {
abstract public <T> castFromString(String value);
abstract public <T> castFromFloat(Float value);
abstract public <T> castFromInt(Int value);
}
public class FloatField extends Field<Float> {
#override
public <Float> castFromString(String value){
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
}
return castValue;
}
}
I did not really like this solution as I would have to add a new abstract method each time I added an extra type to the system.
Any ideas how I could implement this better?
Maybe you could use the Function<T, R> interface?
public abstract class Field<T> implements FieldType<T> {
...
public <F> T convert(F value, Function<F, T> converter) {
try {
return converter.apply(value);
} catch(Exception e) {
return null;
}
}
...
}
And then specify the converter using a lambda expression or a method reference:
field.convert("1234", BigDecimal::new); //with a method reference
field.convert("1234", s -> new BigDecimal(s)) //with a lambda
This would replace all of your convertXXX methods by one since the return type is inferred from the passed Function.
EDIT:
If you want automatic converting, you would of course have to hard-code these since you wouldn't want to write conversion methods for all 4240 classes in the Java API. This gets messy, though. Maybe something like this in a static helper class or in FieldType itself?
public class WhereverYouWantThis {
private static HashMap<Class<?>, HashMap<Class<?>, Function<?, ?>>> converters = new HashMap<>();
static {
putConverter(String.class, Float.class, Float::parseFloat);
}
private static <T, R> void putConverter(Class<T> t, Class<R> r, Function<T, R> func) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) converters.put(t, map = new HashMap<>());
map.put(r, func);
}
public static <T, R> Function<T, R> getConverter(Class<T> t, Class<R> r) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) return null;
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) map.get(r);
return func;
}
public static <T, R> R convert(T o, Class<R> to) {
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) getConverter(o.getClass(), to);
return func == null ? null : func.apply(o);
}
}
I don't think you need generics for this. Instead, just try to create a Float from the input String and return null if there be a problem:
public Float castFromString(String value) {
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
// log here
}
return castValue;
}
The reason I don't think generics are needed is that the types involved in the conversion are named/known in your helper methods.
I have abstract class OptionalComparator<T extends Comparable<T>> implements Comparator<Optional<T>>
So far, so good.
Following the model used by Optional itself, I figured it would be best to have a single instance of this class, and cast it when necessary (for example, to OptionalComparator<Integer>).
So I made private static final OptionalComparator<? extends Comparable<?>> ABSENT_FIRST.
The trouble came when I tried to assign a value. What should the type be?
new OptionalComparator<Comparable<Object>>() {...} doesn't work.
new OptionalComparator<Comparable<Comparable<Object>>>() {...} doesn't work.
new OptionalComparator<Integer>() {...} does work, for example, but I want the least-specific type possible.
What am I doing wrong? How can I make a base-case instance of this class?
You can have multiple implementations of OptionalComparator like this:
private static final OptionalComparator<? extends Comparable<?>> ABSENT_FIRST = new AbsentFirst<>();
private static final OptionalComparator<? extends Comparable<?>> ABSENT_LAST = new AbsentLast<>();
private interface OptionalComparator<T extends Comparable<T>> extends Comparator<Optional<T>> { }
private static class AbsentFirst<T extends Comparable<T>> implements OptionalComparator<T> {
#Override
public int compare(Optional<T> obj1, Optional<T> obj2) {
if (obj1.isPresent() && obj2.isPresent()) {
return obj1.get().compareTo(obj2.get());
} else if (obj1.isPresent()) {
return -1;
} else if (obj2.isPresent()) {
return 1;
} else {
return 0;
}
}
}
private static class AbsentLast<T extends Comparable<T>> implements OptionalComparator<T> {
#Override
public int compare(Optional<T> obj1, Optional<T> obj2) {
if (obj1.isPresent() && obj2.isPresent()) {
return obj1.get().compareTo(obj2.get());
} else if (obj1.isPresent()) {
return 1;
} else if (obj2.isPresent()) {
return -1;
} else {
return 0;
}
}
}
static <T extends Comparable<T>> OptionalComparator<T> absentFirstComparator() {
#SuppressWarnings("unchecked")
OptionalComparator<T> comp = (OptionalComparator<T>) ABSENT_FIRST;
return comp;
}
static <T extends Comparable<T>> OptionalComparator<T> absentLastComparator() {
#SuppressWarnings("unchecked")
OptionalComparator<T> comp = (OptionalComparator<T>) ABSENT_LAST;
return comp;
}
public static void main(String... args) {
OptionalComparator<Integer> absentFirstInt = absentFirstComparator();
System.out.println(absentFirstInt.compare(Optional.of(1), Optional.empty()));
OptionalComparator<Integer> absentLastInt = absentLastComparator();
System.out.println(absentLastInt.compare(Optional.of(1), Optional.empty()));
OptionalComparator<Double> absentFirstDouble = absentFirstComparator();
System.out.println(absentFirstDouble.compare(Optional.of(1.0), Optional.empty()));
OptionalComparator<Double> absentLastDouble = absentLastComparator();
System.out.println(absentLastDouble.compare(Optional.of(1.0), Optional.empty()));
}
Output:
-1
1
-1
1
Guava now provides (since 21.0, and no more #Beta since 27.1) Comparators.emptiesLast(Comparator) and emptiesFirst(Comparator).
Example: Comparator<Optional<Instant>> compareOptInst = Comparators.emptiesLast(Comparator.naturalOrder());
You may just have to do an unsafe cast. Consider how ImmutableList handles the empty-list case:
private static final ImmutableList<Object> EMPTY =
new RegularImmutableList<Object>(ObjectArrays.EMPTY_ARRAY);
/**
* Returns the empty immutable list. This set behaves and performs comparably
* to {#link Collections#emptyList}, and is preferable mainly for consistency
* and maintainability of your code.
*/
// Casting to any type is safe because the list will never hold any elements.
#SuppressWarnings("unchecked")
public static <E> ImmutableList<E> of() {
return (ImmutableList<E>) EMPTY;
}
In this case, it might similarly be easiest to use a raw type instance. As long as you gate all calls that return ABSENT_FIRST with generic casts, this will be fine, and calling code shouldn't have any warnings.
I am trying to convert one generic list of enums to another generic list type but always getting the following compile error:
Is not applicable for the arguments
private static <T extends Enum<T>> List<T> enumListFromEnumList(List<Object> sourceEnumsList, Class<T> classObject) {
List<T> enums = new ArrayList<T>();
if(sourceEnumsList != null) {
for(Object enumObject : sourceEnumsList) {
if (enumObject instanceof Enum)
enums.add(Enum.valueOf(classObject, enumObject.toString().toUpperCase()));
}
}
return enums;
}
Even I tried this:
private static <T extends Enum<T>> List<T> enumListFromEnumList(List<T> sourceEnumsList, Class<T> classObject) {
List<T> enums = new ArrayList<T>();
if(sourceEnumsList != null) {
for(T enumObject : sourceEnumsList) {
enums.add(Enum.valueOf(classObject, enumObject.toString().toUpperCase()));
}
}
return enums;
}
This is how I'm consuming the function:
adapterInfo.setResponseTypeList( enumListFromEnumList(info.getResponseTypeList(), CAPInfo.ResponseType.class));
Updates:
It works when I convert to this:
private static <S extends Enum<S>, T> List<S> enumListFromEnumList(List<T> sourceEnumsList, Class<S> classObject) {
List<S> enums = new ArrayList<S>();
if(sourceEnumsList != null) {
for(T enumObject : sourceEnumsList) {
enums.add(Enum.valueOf(classObject, enumObject.toString().toUpperCase()));
}
}
return enums;
}
So now the question is how to translate "<S extends Enum<S>, T> List<S>" part ( I mean how it works)
Here is what you are looking for (I think) :
enum EnumA {
FIRST,
SECOND,
THIRD
}
enum EnumB {
FIRST,
SECOND,
THIRD
}
private static <A extends Enum<A>, B extends Enum<B>> List<B> enumListFromEnumList(List<A> sourceEnumsList, Class<B> classObject) {
List<B> enums = new ArrayList<B>();
if (sourceEnumsList != null) {
for (A enumObject : sourceEnumsList) {
enums.add(Enum.valueOf(classObject, enumObject.toString().toUpperCase()));
}
}
return enums;
}
public static void main(String[] args) {
List<EnumA> listA = new ArrayList<EnumA>();
listA.add(EnumA.FIRST);
listA.add(EnumA.THIRD);
List<EnumB> listB = enumListFromEnumList(listA, EnumB.class);
System.out.println(listB);
}