I have a array of string I will call a method on this array for each of the element of it ,the method will return one integer,but some of the elements are the same then I do not want to call the method .
for example this is the array:{aa ,bbc ,aa ,dddd};
and for example the method return the length of string

for(i = 0 ,i<array.size();i++){
method(array[i])}

I want if the element is repetitive then it wont call the method and just use the value we already have
what should I do in java ?

you have an array of Strings, and you would return an integer?

what you could do: instantiate a list:

List<String> alreadyChecked = new ArrayList<String>();
for ( i = 0; i < array.size(); i++){
// step 1 ->check if the String is already in the list:
// if so: break;
// else - add it as element to the list, and run the rest of your code
}

Create a Map<String, Integer> that contains all the values you have processed so far, and check that before calling your method.

Edited 1 Year Ago by JamesCherrill

Just for fun, and as part of a "get to know Java 8" campaign, here's a little class that does just that. You create an instance of the class, passing an arbitrary lambda or method ref that takes a String and returns an Integer, then call that instance's calculateOnce method for each String. It keeps a cache of all the String/Integer pairs, and uses that to avoid calling the String to Inetger conversion more than once for the same input.

class CachedStringToIntCalculator {

    private final java.util.function.Function<String, Integer> fn;
    private final Map<String, Integer> cache = new HashMap<>();

    public CachedStringToIntCalculator(java.util.function.Function<String, Integer> f) {
        fn= f;
    }

    public int calculateOnce(String s) {
        Integer i = cache.get(s);
        if (i == null) {
            // System.out.println("Adding value to cache " + s);
            i = fn.apply(s);
            cache.put(s, i);
        }
        return i.intValue();
    }
}

Create the instance with a lambda...

new CachedStringToIntCalculator((s) -> Integer.valueOf(s));

...or a method ref

new CachedStringToIntCalculator(this::myMethod);

where myMethod looks like

public Integer myMethod(String s) {
    ...

Finally, just for a little more fun and some bonus points, you can make this generic - using an arbitrary function that maps a type T to a type R...

class CachedCalculator<T,R> {

    private final java.util.function.Function<T,R> fn;
    private final Map<T,R> cache = new HashMap<>();

    public CachedCalculator(java.util.function.Function<T,R> fn) {
        this.fn= fn;
    }

    public R calculateOnce(T input) {
        R output = cache.get(input);
        if (output == null) {
            output = fn.apply(input);
            cache.put(input, output);
        }
        return output;
    }
}

and use it like

CachedCalculator<String, Integer> c = new CachedCalculator<>(this::myMethod);

Integer result = c.calculateOnce("some string value");

Edited 1 Year Ago by JamesCherrill

...and another thing ...

Funny how the thing you just coded turns out to be already in the API.
I wanted to limit the size of the cache by removing the oldest entry when a given size was reached. Then I discovered LinkedHashMap. It keeps the map with a linked list of values by insertion order, and has an overridable method that says when to remove the oldest entry, eg

int MAX_CACHE = 1000;
LinkedHashMap<T,V> cache = new LinkedHashMap<T,V>(){
        @Override
        protected boolean removeEldestEntry(Map.Entry eldest) {
            return size() > MAX_CACHE;
        }
    };

now you can just use its computeIfAbsent method to return an existing entry, or compute a new one if necessary, insert it in the cache, and remove the oldest entry if necessary

result = cache.computeIfAbsent(input, this::myMethod);

simples!

Edited 1 Year Ago by JamesCherrill

This article has been dead for over six months. Start a new discussion instead.