You assume that there are a list of an object. The list is sorted by one or more field of that object. So according to sorted list, i want to set a field of that object with incremental-value.
For clarifying, pay attention to the below example:
public class ObjectTest {
int id;
int userId;
int code;
}
As above ObjectTest, any user has its own code.
There are a list of ObjectTest.
List<ObjectTest> objTests;
It is sorted:
objTests.sort(Comparator.comparing(DataSet::getUserId).thenComparing(DataSet::getCode));
So after sorting by userId and code, i want to set value from 1 to where any user has the its own code. The incremental value again is resetted to 1 when userId is changed.
If there are the following collection of ObjectTest.
id userId code
--------------------------------
100 5
200 6
100 7
200 9
200 10
100 2
After the above scenario that is explained, the following collection will be:
id userId code
1 100 2
2 100 5
3 100 7
1 200 6
2 200 9
3 200 10
Is it possible with lambda expression in java
Increment Operator (++) The increment (++) operator (also known as increment unary operator) in Java is used to increase the value of a variable by 1. Since it is a type of a unary operator, it can be used with a single operand.
6.2 The below example uses computeIfAbsent to provide a default value for the key; computeIfPresent to update or increase the key value. 6.3 There is also a putIfAbsent to update the value only if the key doesn't exist. Map<String, Integer> map = new HashMap<>(); for (int i = 0; i < 10; i++) { //map.
Something along the lines of this should work:
List<ObjectTest> resultSet =
objTests.stream()
.sorted(Comparator.comparing(ObjectTest::getUserId).thenComparing(ObjectTest::getCode))
.collect(Collectors.groupingBy(ObjectTest::getUserId, LinkedHashMap::new, Collectors.toList()))
.values()
.stream()
.map(e -> {
IntStream.range(0, e.size())
.forEach(i -> e.get(i).setId(i + 1));
return e;
})
.flatMap(Collection::stream)
.collect(Collectors.toList());
Note, I have not compiled this code.
You can create a map of userId
to a scoped atomic integer object, then iterate over the sorted list to set the ID.
Map<Integer, AtomicInteger> userIds =
objTests.stream()
.map(obj -> Integer.valueOf(obj.getUserId()))
.distinct()
.collect(Collectors.toMap(Function.identity(),
(id) -> new AtomicInteger(1)));
The above map contains an atomic integer object for each unique userId
.
objTests.stream()
.forEach(obj -> obj.setId(userIds.get(obj.getUserId())
.getAndIncrement()));
This last code just iterates over the sorted list, then assigns an id
read from the atomic integer associated with the user ID on the instance.
It may be possible but you should most likely not solve it with the streams API.
The reason is that the streams API ist Javas implementation of functional programming and one of the key assumptions in FP is that objects (or better any data) have no relationship to each other and no function changes the state of the Input data.
Therefore your requirement breakes with FPs key assumption.
What is your idea to get my goal? – reza ramezani matin
Group objects by user ID:
Map<Integer,ObjectTest> userIdMap= objTests.stream()
.collect(Collectors.groupingBy(
ot ->ot.userId , ot ->ot
));
enumerate with legacy Looping:
for(Collection<ObjectTest> ol : userIdMap.values()){
objectList = new ArrayList(ol);
Colections.sort(ol, /* comparator here*/);
for(int id = 0; id < ol.size();)
objectList.get(id).id=++id;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With