Jade_Layyne
Jade_Layyne

Reputation: 21

Java 8 loop arraylist of object and add element if condition verified

I am trying to use java 8 stream. I checked the other posts and I do not understand why my code below is causing an error. Someone can tell me what is wrong with my code? Thank you

private OptList myFunction(OptList childOpts, Opt subOpt) {
        OptList results = new OptList();
        for (Opt o : childOpts) {
            if ((subOpt.getOptPri() == null || subOpt.getOptPrices().isZeroPrice())
                    && (o.getOptPrices() == null || o.getOptPrices().isZeroPrice())) 
            {
                results.add(o);
            } else 
            if (subOpt.getOptPrices() != null && o.getOptPrices() != null) {
                if (subOpt.getOptPrices().getPrice(PriceType.MS).equals(o.getOptPrices().getPrice(PriceType.MS))
                        && subOpt.getOptPrices().getPrice(PriceType.DISC).equals(o.getOptPrices().getPrice(PriceType.DISC))
                        && subOpt.getOptPrices().getPrice(PriceType.INV).equals(o.getOptPrices().getPrice(PriceType.INV))
                        && subOpt.getOptPrices().getPrice(PriceType.INV_DISC).equals(o.getOptPrices().getPrice(PriceType.INV_DISC))) 
                {
                    results.add(o);
                }
            }
        }
        return results;
    }

    private OptionList myFunction(OptList childOpts,
                                            Opt subOpt) {
        return childOpts.stream()
                .filter(o -> (((subOpt.getOptPrices() == null || subOpt.getOptPrices().isZeroPrice()) && (o.getOptPrices() == null || o.getOptPrices().isZeroPrice()))
                        || ( (subOpt.getOptPrices() != null && o.getOptPrices() != null) && (subOpt.getOptPrices().getPrice(PriceType.MS).equals(o.getOptPrices().getPrice(PriceType.MS))
                        && subOpt.getOptPrices().getPrice(PriceType.DISC).equals(o.getOptPrices().getPrice(PriceType.DISC))
                        && subOpt.getOptPrices().getPrice(PriceType.INV).equals(o.getOptPrices().getPrice(PriceType.INV))
                        && subOpt.getOptPrices().getPrice(PriceType.INV_DISC).equals(o.getOptPrices().getPrice(PriceType.INV_DISC)))     )))
                .collect(Collectors.toList());
    }

Upvotes: 0

Views: 967

Answers (3)

wumpz
wumpz

Reputation: 9131

You are using your own List implementation. Collectors.toList() does return a standard collection type: List<Opt>.

Therefore your first option is to use the standard like

private List<yourType> myFunction(OptList childOpts, Opt subOpt)

or if OptionList implements List, then you are able to change your collect call to:

Collectors.toCollection(OptionList::new)

This little example provides some info on the returned types and standardtypes:

List<String> values = Arrays.asList("1", "2", "3");
System.out.println( 
   values.stream().collect(toList())
    .getClass().getTypeName() );
System.out.println( 
   values.stream().collect(toCollection(LinkedList::new))
    .getClass().getTypeName() );

It prints:

java.util.ArrayList
java.util.LinkedList

Upvotes: 0

Olivier Croisier
Olivier Croisier

Reputation: 6149

Let's look at the myFunction method :

private OptionList myFunction(OptList childOpts, Opt subOpt) {
    return childOpts.stream()
            .filter(...)
            .collect(Collectors.toList());
}

It takes a list of Opts (OptList), eliminates those who don't match a certain criteria, then groups them back with the toList() collector, which returns a java.util.List of the items that are streamed.

So the expression's return type (and thus the whole method's return type) should be List<Opt> or a supertype of it (eg. Collection<Opt>).

Your current method signature is therefore wrong, and the compiler complains.

Upvotes: 0

Willis Blackburn
Willis Blackburn

Reputation: 8204

I understand that you have two functions, one implemented using regular collection operations, and the other implemented using streams, and you want to know why the second doesn't work.

I don't know what OptList is, but it's not going to be a List<Opt>, which is what collect(Collectors.toList()) is going to return. You need some way to make the collect function return OptList.

You have two options.

If OptList is a (extends) Collection<Opt>, then you can use toCollection and pass an a function that produces an OptList:

childOpts.stream(). (other stuff) .collect(Collectors.toCollection(OptList::new))

This works because the collect method knows how to call the add method of the resulting Collection.

If OptList is not a collection type, then you can still use collect, but you have to build your own collector. You will need to supply a function that creates the output type, a function to add a new member to it, and a function to combine two of the output types into one, which will be used if you are collecting parallel streams.

It will probably look something like this:

childOpts.stream(). (other stuff) .collect(OptList::new, OptList::add, OptList::addAll)

If OptList doesn't have an addAll, then you can try passing null (not sure if that will work!) or passing a function that throws UnsupportedOperationException.

Upvotes: 1

Related Questions