Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange looking guava code

Tags:

java

guava

I'm having trouble following the below code snippet:

prices = pricesService.getProductsByCategory(category);
List<Double> discountedPrices = 
    Lists.newArrayList(Iterables.transform(prices, new Function<Double, Double>() {
        public Double apply(final Double from) {
            return from *.88;
        }
    }));

I know what the result of the code is and it's correct in unit tests, but I'm not overly familiar with guava or how/why this implementation works. Also currently it doesn't appear to be safe if there is a null value in the list 'prices' either? So what I'm after:

  1. A general explanation of how the code works.
  2. Is it currently null safe? If not how can it made to be?
like image 1000
Joe Schmuck Avatar asked Jul 10 '13 03:07

Joe Schmuck


2 Answers

It creates a new List of Doubles which are 0.88 * the original.

The constructs are:

Anonymous inner class

This is a way how callbacks / closures are sometimes done in Java. See also Java tutorial on this.

new Function<Double, Double>() {
    public Double apply(final Double from) {
        return from *.88;
    }
}

Callback using the above function

Iterables.transform(prices, *func*)

Converting the result to ArrayList

The result of the above is an Iterable, so it needs to be stored to a list. See also Lists.newArrayList vs new ArrayList

Lists.newArrayList( ... )
like image 142
Ondra Žižka Avatar answered Oct 07 '22 18:10

Ondra Žižka


1) So Guava has a static util class callled Iterables that has a method called transform that takes a collection and a guava Function instance as variables. In this case the developer used an in line anonymous function that returns a double value by the overridden method "apply".

A more traditional implementation would have been something like this:

List<Double> discountedPrices = Lists.newArrayList();
for(Double price: prices) {
    discountedPrices.add(price * .88);
}

2) Not entirely sure what you mean by null safe? assuming you mean what would happen if the list 'prices' contained a null value? If so guava has another solution for you in Iterables.filter(Collection, Predicate). In your case you'd want to filter out nulls and there is a built in guava Predicate for this purpose. So in your case you could do something like:

 prices = Iterables.filter(prices, Predicates.notNull();
 List<Double> discountedPrices = Lists.newArrayList(
 Iterables.transform(prices, new Function<Double, Double>() {
        public Double apply(final Double from) {
            return from *.88;
        }
    }));

This first line returns the prices collection without nulls in it and the 2nd would behave exactly as before and you could safety assume nulls had been removed already.

like image 44
Durandal Avatar answered Oct 07 '22 16:10

Durandal