Сортировка и проверка, находятся ли числа в последовательном порядке, используя Java8

#java #java-8

#java #java-8

Вопрос:

Я пытаюсь отсортировать список длинных и проверить, находятся ли числа в последовательном порядке, начиная с 1. Я хочу делать все в java8 / streams

 //sorting first
 List<Long> sortedNums = request.stream().map(Request::getSequence)
                .collect(Collectors.toList()).stream().sorted().collect(Collectors.toList());

//getting first num to see if the seq starting from 1
Optional<Long> first = sortedNums.stream().findFirst();

        if (first.isPresent()) {
            if (first.get() != 1) {
                throw new BadRequestException("Sequence should start from 1");
            }
        }
//checking if the list is in consecutive order
 if(!isConsecutive(sortedNums)) {
            throw new BadRequestException("Sequences should be in consecutive order");
        }
 private boolean isConsecutive(List<Long> list) {
        for (int i = 1; i < list.size(); i  ) {
            if (list.get(i - 1)   1 != list.get(i)) {
                return false;
            }
        }
        return true;
    }
  

Я пытаюсь понять, есть ли более оптимальный способ сделать это с помощью stream, объединяющего все операторы в один или два.

Комментарии:

1. Какой смысл проверять порядок после его сортировки?

2. .collect(Collectors.toList()).stream() бессмысленно.

3. @shmosel Я думаю, что OP проверяет, что числа находятся в последовательности, а не только в порядке.

4. Если вы уже собираетесь выбросить, если первый элемент не один, не беспокойтесь о необязательном и просто сделайте: first = sortedNums.stream().findFirst().orElse(-1);

5. Ах, вы имеете в виду, являются ли они последовательными.

Ответ №1:

Я бы сделал это разными небольшими методами вместо того, где вы делаете все:

 public static boolean startsWith1(List<Long> list){
    //return list.stream().sorted().findFirst().get() == 1; //see @Holger's comment
    return Collections.min(list) == 1;
}
// The sum of all numbers from 1 to n = n * (n 1) /2; 
// you can use that to check if your list contains all numbers from 1 to n
public static boolean isConsecutive(List<Long> list){
    long n = list.size();
    return list.stream().mapToLong(Long::longValue).distinct().sum() == n * (n 1) /2;
}
public static void doSomething(List<Long> list) throws BadRequestException{
    if(!startsWith1(list)){   
        throw new BadRequestException("Sequence should start from 1 ");
    }
    if(!isConsecutive(list)) {
        throw new BadRequestException("Sequences should be in consecutive order");
    }
    else{
        // do whatever with your list
    }
}
  

Комментарии:

1. .sorted().findFirst() это неэффективный способ получить .min(Comparator.naturalOrder()) … Здесь вы можете сделать еще проще: return Collections.min(list) == 1;

2. @Holger Большое вам спасибо за этот намек. Я только что перенял это из кода OP и не думал об этом много. Действительно Collections.min(list) , это более элегантно, чем то, что у меня выше. Обновлено.