Pergunta

I have little problem with code design that use new streaming API from Java 8. I would like to learn new things and one of the task is:

Reject max and min from list. List not contains duplicates.

Looks simple? Nope... My code:

  List<Integer> ranges = Lists.newArrayList(new Range(1, 15));
        List<Integer> collect = ranges.stream()
                .filter(x -> x != ranges.stream()
                        .mapToInt(Integer::intValue)
                        .max()
                        .getAsInt())
                .filter(x -> x != ranges.stream()
                        .mapToInt(Integer::intValue)
                        .min()
                        .getAsInt())

                .collect(Collectors.toList());
        assertThat(collect).hasSize(13);   // OK
        assertThat(collect).isEqualTo(Lists.newArrayList(new Range(2,14)));   // OK

this code is good (if only we dont have duplicates of min/max, but this is not a core problem here) but problem is that I use here three streams. First is main stream, second to remove max and third to remove min. Is there any possibility to do this task in one stream?

//edit: Very primitive Scala version:

val list = List.range(1, 15).sortWith(_>_).tail.reverse.tail

with additional sort because we could have shuiffeled list.

Foi útil?

Solução 2

The solution is not very efficient, but I think it follows your requirements - it does what you want and it is in one single pipeline - one single sequence of bulk data operations, how Java 8 calls it.

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Stream<Integer> ranges = Stream.iterate(1, i -> i + 1).limit(15);
List<Integer> collect = ranges
    .sorted(Comparator.reverseOrder()) // sort the stream from the highest to the smallest
    .skip(1)                           // discards 1 element from the beginning
    .sorted()                          // sort the stream from the smallest to the highest
    .skip(1)                           // discards 1 element from the beginning
    .collect(Collectors.toList())     
    ;

But, as fge suggested and Marco13 wrote in their comment below your question, it would be better and much more efficient just to sort the stream, terminate the pipeline to a list and then remove the first and the last member :P Or even faster without sort - go through all the elements, find min and max, remember their position and then remove them.

Outras dicas

Don't forget Collection.removeIf. You can compute min and max, and then do:

list.removeIf(x -> x == min || x == max);

(This also deals well with duplicates.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top