busywithJava
busywithJava

Reputation: 41

Java stream: Difficulty in object property update

I have one list List with a quite a number of fields, need to create a List in a single pass using stream.

  1. We need to mark the field current true in the List, for the least positive integer in the input List

    Input:

    [PT(pn=-1, endDate=2019-01-11, dp=MAR 2019,..),           
    PT(pn=4, endDate=null, dp=APR 2019,..),        
    PT(pn=6, endDate=2019-05-11, dp=MAY 2019,..)]       
    

    Output:

    [OP(pn=11, current=false, dp=MAR 2019),
     OP(pn=4, current=true, dp=APR 2019),
     OP(pn=6, current=false, dp=MAY 2019)]    
    
class OP{       
   Integer pn;      
   Boolean current;      
   String dp;       
} 
List<OP> filteredList11 = availablePT.get()
    .stream()
    .map(e->new OP(e.getPn(),**,e.getDp()))
    .collect(Collectors.toList());

I am bit confused how to derive the logic to update the current flag(**) as true for the least positive integer in a single loop.

Upvotes: 2

Views: 144

Answers (3)

Hadi
Hadi

Reputation: 17289

You can do something like this :

first find the least positive PT object.

Optional<PT> latestPositive = availablePT.stream()
                             .filter(pt -> pt.getPn() > 0)
                             .min(Comparator.comparingInt(PT::getPn));

then by stream over availablePT list create OP object.

List<OP> filteredList11 = availablePT.stream()
            .map(pt -> new OP(pt.getPn(),
                              pt.equals(latestPositive.orElse(null)), pt.getDp()))
            .collect(Collectors.toList());

If you are interested in to use single stream do this:

first write a custom comparator.

 Comparator<PT> ptComparator = (o1, o2) -> {
        if (o2.getPn() < 0) {
            if (o1.getPn() > 0)
                return -1;
        } else if (o2.getPn() > 0) {
            if (o1.getPn() < 0)
                return 1;
        }
        return Integer.compare(o1.getPn(), o2.getPn());
    };

then sort list with your comparator

AtomicInteger integer = new AtomicInteger(0);
 List<OP> filteredList11 = availablePT.stream()
          .sorted(ptComparator)
          .map(pt -> new OP(pt.getPn(), integer.incrementAndGet()==1, pt.getDp()))
          .collect(Collectors.toList());  

Upvotes: 1

MadaManu
MadaManu

Reputation: 886

Here is another approach. Have a OP constructor that takes in a PT and maps all the fields, plus the extra boolean set by default to false.

Then do something like this:

List<OP> ops = availablePT.stream().map(dp -> {return new OP(dp);})
 .filter(line -> line.getPn()!=null && line.getPn().doubleValue()>=0)
 .sorted(Comparator.comparingInt(OP::getPn))
 .collect(Collectors.toList());
if(ops!=null && !ops.isEmpty()) {
   ops.get(0).setCurrent(true);
}

This basically creates the new objects, then filters the negatives out, then sorts the possitives, and then you're guaranteed that the op with smallest dp value is first, so set it's boolean to true

Upvotes: 1

Cường Lư Quốc
Cường Lư Quốc

Reputation: 338

Here is your required:

AtomicBoolean isFirst = new AtomicBoolean(true);
    List<OP> filteredList11 = availablePT.get()
        .stream()
        .map(e->new OP(e.getPn(),**,e.getDp()))
        .sorted(Comparator.comparingInt(OP::getPn))
        .peek(e -> {
                        if (e.getPn() % 2 == 0) {
                            e.setCurrent(isFirst.getAndSet(false));
                        }
                    })
        .collect(Collectors.toList());

Upvotes: 0

Related Questions