code: static <T> void bucketSort(final List<? extends T> c, final int fromIndex, final int toIndex, final Comparator<? super T> cmp) {
          N.checkFromToIndex(fromIndex, toIndex, c == null ? 0 : c.size());
  
          if ((N.isNullOrEmpty(c) && fromIndex == 0 && toIndex == 0) || fromIndex == toIndex) {
              return;
          }
  
          if (toIndex - fromIndex < 32) {
              sort(c, fromIndex, toIndex, cmp);
              return;
          }
  
          final Comparator<? super T> comparator = cmp == null ? Comparators.NATURAL_ORDER : cmp;
          final Multiset<T> multiset = new Multiset<>();
          ListIterator<T> itr = (ListIterator<T>) c.listIterator(fromIndex);
          int i = fromIndex;
  
          while (itr.hasNext()) {
              if (i++ >= toIndex) {
                  break;
              }
  
              multiset.add(itr.next());
          }
  
          final Map<T, Integer> m = multiset.toMapSortedBy(new Comparator<Map.Entry<T, MutableInt>>() {
              @Override
              public int compare(Entry<T, MutableInt> a, Entry<T, MutableInt> b) {
                  return comparator.compare(a.getKey(), a.getKey());
              }
          });
  
          itr = (ListIterator<T>) c.listIterator(fromIndex);
  
          for (Map.Entry<T, Integer> entry : m.entrySet()) {
              final T key = entry.getKey();
              for (int j = 0; j < entry.getValue(); j++) {
                  itr.next();
                  itr.set(key);
              }
          }
      }
docs: Note: All the objects with same value will be replaced with first element with the same value.
  
  @param c
  @param fromIndex
  @param toIndex
  @param cmp