1

I have an Arraylist of the Cells from an Excel sheet. I want to create subarraylists of size 50 from the Arraylist of Cells I actually have, beginning from the index of 1590 and ending with size()-700.

I want to get the highest number from every subarraylist and put it in the new Arraylist. in the new Arraylist there should be only the highest values of each subarraylist.

Input data is my Arraylist of Cells.

With this code I get more than 50 numbers and it's not always the highest value. Has anyone an idea?

This is my code:

int partitionSize = 50;

List<List<Cell>> partitions = new ArrayList<>();
List <Cell> high = new ArrayList();
Cell max = data.get(1590);

for (int i = 1590; i < data.size()-700; i += partitionSize) {
    partitions.add(data.subList(i, Math.min(i + partitionSize, data.size()-700)));
}

for (List<Cell> list : partitions) {
    for (int i = 1; i < list.size(); i++) {
        if (list.get(i).getNumericCellValue() > max.getNumericCellValue()) {
            max = list.get(i);
        }
        high.add(max);
    }
}
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • Hi, multiple community members took time to answer your question. Please consider acknowledging one with a check. – Oliver Feb 17 '22 at 18:23

2 Answers2

1

The list of partitions may be generated using IntStream::iterate:

int start = 1590;
int end = data.size() - 700;
int size = 50;
List<List<Cell>> partitions = IntStream
    .iterate(start, i -> i < end, i -> i + size) // IntStream
    .mapToObj(i -> data.subList(i, Math.min(i + size, end)))
    .collect(Collectors.toList())
;

Then the list of cells with maximal values can be retrieved as follows:

List<Cell> maxPerRange = partitions
    .stream() // Stream<List<Cell>>
    .map(list -> list.stream() // Stream<Cell>
                     .max(Comparator.comparing(Cell::getNumericCellValue))
                     .get()
    )
    .collect(Collectors.toList());

Similarly, the list of maximal values may be created without explicit splitting the input data in sublists, just by using the appropriate ranges similar to the nested loops:

List<Cell> maxPerRange = IntStream
    .iterate(start, i -> i < end, i -> i + size) // IntStream
    .mapToObj(i -> IntStream.range(i, Math.min(i + size, end))
            .mapToObj(data::get)
            .max(Comparator.comparing(Cell::getNumericCellValue))
            .get()
    )
    .collect(Collectors.toList());
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • Thank you very much it helps me a lot. It didnt know the IntStream API. I like both solutions, the last one its very compact and the first one also great! –  Nov 26 '21 at 23:36
  • 1
    This specific version of `IntStream/Stream::iterate` method was introduced in Java 9 – Nowhere Man Nov 26 '21 at 23:52
0

You could take advantage of the Stream API.

For example:

List<List<Integer>> partitions = new ArrayList<>();
List<Integer> high = partitions.stream()
    .map(partition -> partition.stream().max(Integer::compareTo))
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());
Oliver
  • 1,465
  • 4
  • 17
  • What should i do instead of Optional should i put the type instead of and isPresent? The Type of my Arraylist is Cell there is no compareTo method. –  Nov 25 '21 at 19:03
  • You would replace `Integer::compareTo` with a comparison method of two instances of `Cell`, but keep `Optional::isPresent`. I'm sorry, I should have considered: Is Java new to you? – Oliver Nov 26 '21 at 23:11
  • Yes it is new to me, the comment uo p to yours helps me a lot, but thank you for your advice :) –  Nov 29 '21 at 23:07
  • @Nando94 Sorry, I am confused by your last comment. Did my solution work for you or do you need more assistance? – Oliver Nov 30 '21 at 01:39