0

I'm trying to select the first and last 25% of objects in a list and insert them into a second list. I've calculated the percentage and created a loop to select the first 25% of objects, but I can't figure out how to select the last 25% of objects in the list.

List<NodeObject> selectedNodes = new ArrayList();

//Calculate the percentage
double listLength = nodes.size();
double percentage = (listLength / 100) * 25;
int listQuarter = (int) percentage;

//Select first 25%
for (int i = 0; i < listQuarter; i++) {
    NodeObject node = nodes.get(i);
    selectedNodes.add(node);
    }
1
  • Rather use a Map<percentage, NodeObject> and iterate through it to get the vals.
    – pikkuez
    Commented Feb 4, 2020 at 12:41

5 Answers 5

4

It is simpler than it looks. Just start the iteration from the last quarter's start then end at the length of the list like this:

//Select last 25%
for (int i = listLength - listQuarter; i < listLength; i++) {
    NodeObject node = nodes.get(i);
    selectedNodes.add(node);
}
3
double percentage = (listLength / 100) * 25;

This won't work for lists shorter than 100 (it returns 0). It also prodices very wrong results for smaller values because the division is made with ints not doubles and the result is cast to double only when the calculation is ready. The correct way is to use a double in the division, which forces the compiler to treat the intermediate results as doubles.

double percentage = (listLength / 100.0) * 25;

Or to put it short:

double percentage = listLength * 0.25;
1

Use subList to get a portion of the list, and addAll to add it all in one go to the other list:

selectedNodes.addAll(nodes.subList(listLength - listQuarter, listLength));

Aside from being concise, this is more efficient because selectedNodes knows that it's going to have a certain number of elements added to it, so it can make necessary changes to its internal structure in one go, rather than one thing at a time.

1
1

Here's a solution with streams that uses limit and skip:

var list = List.of(1, 2, 3, 4, 5, 6 ,7 ,8 ,9, 10);

// Last 25%
list.stream()
    .skip(Math.round(list.size() * 0.75))
    .collect(Collectors.toList());

// First 25%
list.stream()
    .limit(Math.round(list.size() * 0.25))
    .collect(Collectors.toList());
0

Well, if you want to keep doing what you're doing, just loop backwards.

// Select last 25%
for (int i = nodes.size()-1; i > nodes.size()-listQuarter; i--) {
    NodeObject node = nodes.get(i);
    selectedNodes.add(node);
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.