I have List with following information.
public class PriceDetails {
public String materialId;
public String price;
public String priceEndDate;
}
List data is as follows:
List<PriceDetails> priceList = new ArrayList<>();
priceList1 [priceEndDate=2022-04-29 00:00:00.000000, price=1.59, materialId=10054700],
priceList2 [priceEndDate=2022-03-31 00:00:00.000000, price=1.64, materialId=10054700],
priceList3 [priceEndDate=2022-05-26 00:00:00.000000, price=3.1, materialId=10063200]]
I want to create another list with following information from above one.
As we can see, priceList1, and priceList2 have materialId same. So I need to take the one whose priceEndDate is latest among first two dates. So my resultant list should be as below,
priceList1 [priceEndDate=2022-04-29 00:00:00.000000, price=1.59, materialId=10054700],
priceList3 [priceEndDate=2022-05-26 00:00:00.000000, price=3.1, materialId=10063200]]
I tried this so far:
for(PriceDetails unit :priceList) {
if(map.containsKey(unit.getmaterialId())) {
map.put(unit.getmaterialId(), <notgettingwhattoputhere>));
}else {
}
}
Please help in achieving same.
CodePudding user response:
This might be the answer to your question. But try to avoid having price and priceEndDate as a String.
static class PriceDetails {
public String materialId;
public String price;
public String priceEndDate;
public PriceDetails(String materialId, String price, String priceEndDate) {
super();
this.materialId = materialId;
this.price = price;
this.priceEndDate = priceEndDate;
}
public String toString() {
return String.format("[materialId: %s, price: %s, priceEndDate:%s]", this.materialId, this.price, this.priceEndDate);
}
}
public static void filter() throws ParseException {
List<PriceDetails> priceList = new ArrayList<>();
PriceDetails priceList1 = new PriceDetails("10054700", "1.59", "2022-04-29 00:00:00.000000");
PriceDetails priceList2 = new PriceDetails("10054700", "1.64", "2022-03-31 00:00:00.000000");
PriceDetails priceList3 = new PriceDetails("10063200", "3.1", "2022-05-26 00:00:00.000000");
priceList.add(priceList1);
priceList.add(priceList2);
priceList.add(priceList3);
Map<String, PriceDetails> map = new HashMap<>();
for(PriceDetails unit :priceList) {
if(map.containsKey(unit.materialId)) {
if((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(unit.priceEndDate)).after((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(map.get(unit.materialId).priceEndDate)))) {
map.put(unit.materialId, unit);
}
} else {
map.put(unit.materialId, unit);
}
}
System.out.println(map.values());
}
Output:
[[materialId: 10054700, price: 1.59, priceEndDate:2022-04-29 00:00:00.000000], [materialId: 10063200, price: 3.1, priceEndDate:2022-05-26 00:00:00.000000]]
CodePudding user response:
It is possible to collect the data in the list and pick up the latest price, then retrieve the values()
from the obtained map, providing that PriceDetails
class has relevant getters for its member fields:
- using the following collectors:
Collectors.groupingBy
to group the price details by their idsCollectors.maxBy
to find the latest price detail with the help ofComparator.comparing
by the appropriate getter (here the price end date)Collectors.collectingAndThen
to convert theOptional
returned at the previous step into appropriatePriceDetail
:
List<PriceDetails> latest = new ArrayList<>(
data.stream()
.collect(Collectors.groupingBy(
PriceDetails::getMaterialId,
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(PriceDetails::getPriceEndDate)
),
Optional::get
)
))
.values()
);
- Using
Collectors.toMap
with merge function usingBinaryOperator::maxBy
:
List<PriceDetails> latest = new ArrayList<>(
data.stream()
.collect(Collectors.toMap(
PriceDetails::getMaterialId,
price -> price,
BinaryOperator.maxBy(
Comparator.comparing(PriceDetails::getPriceEndDate)
)
))
.values());
Without Stream API, the reduced list may be retrieved similarly from the map of priceId to the price using Map::merge
function:
Map<String, PriceDetails> map = new LinkedHashMap<>();
for (PriceDetails pd : data) {
map.merge(pd.getMaterialId(), pd, BinaryOperator.maxBy(
Comparator.comparing(PriceDetails::getPriceEndDate)
));
}
List<PriceDetails> latest2 = new ArrayList<>(map.values());