Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a list of numbers with all 0's at the end of result

I have the list of persons and if the list of Input is 3,0,2,7,0,8

I want the output to be 2,3,7,8,0,0

With the following code, i can sort only non zero numbers to get 2,3,7,8 as output.

sortedList = personList.stream()
                       .filter(Person -> Person.getAge()>0)
                       .sorted(Comparator.comparingInt(Person::getAge))
                       .collect(Collectors.toList());

zeroList=personList.stream()
                       .filter(Person -> Person.getAge()==0)
                       .collect(Collectors.toList());

sortedList.addAll(zeroList);

Can the above two statements be merged into a single statement?

like image 457
Sujan Davangere Sunil Avatar asked Nov 08 '17 21:11

Sujan Davangere Sunil


People also ask

How do you sort string integers?

The split() method of the string class accepts a string representing a delimiter, splits the current string into an array of tokens. Using this method split the given string into an array of tokens. The parseInt() method of the Integer class accepts a String value and converts it into an integer.

Can we sort list of list in Java?

Collections class sort() method is used to sort a list in Java. We can sort a list in natural ordering where the list elements must implement Comparable interface. We can also pass a Comparator implementation to define the sorting rules.

Can you sort a list in O N?

You can use radix sort, counting sort, there are lots of O(n) sorts.


3 Answers

You can make sure that zeros go to the end by writing an appropriate comparator:

sortedList = personList.stream()
   .sorted((p1, p2) -> {
      int a = p1.getAge();
      int b = p2.getAge();
      if (a == 0 && b == 0) return 0;
      if (a == 0) return 1;
      if (b == 0) return -1;
      return Integer.compare(a, b);
   })
   .collect(Collectors.toList());

Or slightly more compactly:

sortedList = personList.stream()
   .sorted((p1, p2) -> {
      int a = p1.getAge();
      int b = p2.getAge();
      return a == 0 || b == 0 ? Integer.compare(b, a) : Integer.compare(a, b);
   })
   .collect(Collectors.toList());
like image 88
janos Avatar answered Oct 06 '22 00:10

janos


A nice simple way to put 0s at the end of the sort is to treat them as large values in the comparator:

Comparator.comparingInt(p -> p.getAge() == 0 ? Integer.MAX_VALUE : p.getAge())
like image 26
sprinter Avatar answered Oct 05 '22 22:10

sprinter


What you want, is a rotation; when you simply sort by age, the elements are in the right order, when you consider the result list to be a ring, so you only want to start the list after the last zero-age value:

┌───────────────────────────┐
└─ 0  0  2  3  7  8       <─┘
         2  3  7  8  0  0 
sortedList = personList.stream()
    .sorted(Comparator.comparingInt(Person::getAge))
    .collect(Collectors.toCollection(ArrayList::new));
Collections.rotate(sortedList, -(int)personList.stream().filter(p->p.getAge()==0).count());

Alternatively, you can rotate the age values within the int value range while comparing. This works, because we can preclude negative ages, so we can rotate the numbers so that zero becomes the MAX_VALUE while all other numbers keep their relative order.

sortedList = personList.stream()
    .sorted(Comparator.comparingInt(p -> p.getAge()-Integer.MIN_VALUE-1))
    .collect(Collectors.toList());

By the way, this is equivalent to

sortedList = personList.stream()
    .sorted((p1, p2) -> Integer.compareUnsigned(p1.getAge()-1, p2.getAge()-1))
    .collect(Collectors.toList());

Understanding the two's complement is needed to understand the solution.

like image 37
Holger Avatar answered Oct 05 '22 23:10

Holger