Java реализация пузырьковой сортировки в функциональном стиле

2

Как реализовать следующий алгоритм сортировки Bubble в функциональном (Java 8) способом?

public static final <T extends Comparable<T>> List<T> imperativeBubbleSort(List<T> list) {
    int len = list == null? 0: list.size();
    for(int j = len-1; j > 0; j--) {
        for(int k = 0; k < j; k++) {
            if(list.get(k+1).compareTo(list.get(k)) < 0) {
                list.add(k, list.remove(k+1));
            }
        }
    }
    return list;
}
  • 1
    Пузырьковая сортировка плохо подходит для функционального программирования в целом. Слияния списков и кучи более естественны в этом контексте.
Теги:
functional-programming
order
bubble-sort

5 ответов

3
Лучший ответ

Это будет зависеть от того, что вы подразумеваете под функциональностью. Если вы имеете в виду просто передавать функции в качестве объектов первого класса, то вы должны изменить свою подпись метода:

public static final <T> List<T> imperativeBubbleSort(List<T> list, Comparator<T> comparisonFunction)

Таким образом, логика сравнения может быть предоставлена в качестве аргумента.

Если вы имеете в виду, что вы будете полностью функционировать, а вовсе не процедурные, я бы назвал это анти-шаблоном. Несмотря на то, что вы можете услышать, Java 8 не полностью поддерживает функциональное программирование. Ключевой особенностью, которой он отсутствует, является оптимизация хвостового вызова. Без него вид программирования без циклы, который определяет функциональное программирование, скорее всего, приведет к сбою вашего JVM для относительно небольших значений.

Более подробную информацию об оптимизации хвостовых вызовов и JVM можно найти здесь: http://www.drdobbs.com/jvm/tail-call-optimization-and-java/240167044

1

Самый короткий путь, о котором я мог думать, - это следовать. Там, где вводится listForBubbleSort, и вызывается bubbleSorted.

        List<Integer> listForBubbleSort = Arrays.asList(5, 4, 3,  7, 6, 9, 11, 10, 21);

        final List<Integer> copiedList = new ArrayList<>(listForBubbleSort);
        copiedList.add(Integer.MAX_VALUE);

        final List<Integer> bubbleSorted = new ArrayList<>();

        copiedList.stream()
                .reduce((c, e) ->
                    {
                        if ( c < e ){
                            bubbleSorted.add(c);
                            return e;
                        }
                        else
                        {
                            bubbleSorted.add(e);
                            return c;
                        }
                    }
                );
        System.out.println(bubbleSorted);

Я все еще чувствую, что если бы мы могли создать пользовательский коллекционер и просто передать коллекционеру коллекцию потока, это было бы здорово. Подобно тому, как мы передаем поток (toList()) в поток. Но все же, изучая Java 8, нужно больше времени для создания того же. Если кто-то уже создал пользовательский коллекционер, поделитесь им.

  • 0
    Да, на самом деле я обнаружил, что попытка решить этот алгоритм с использованием функционала противоречит принципам функционального программирования.
  • 0
    Решение использует функции Java8, но оно не работает, потому что у вас изменяемое состояние (вы добавляете элементы в изменяемый список).
1

Я не думаю, что Java 8 предоставит большую помощь в этом случае, чтобы написать сортировку пузырьков в функциональном стиле.

Например, эта реализация реализации Bubble sort в Haskell может быть смоделирована на Java следующим образом. Он более функциональный, поскольку он использует рекурсию вместо итерации, но все же Java 8 не имеет таких функций, как сопоставление образцов, конкатенация списков и т.д., Чтобы выразить алгоритмы в более функциональном стиле.

public static final <T extends Comparable<T>> List<T> functionalBubbleSort(List<T> list) {
    for (int i = 0; i < list.size(); i++) {
        list = onePassSort(list);
    }
    return list;
}

public static final <T extends Comparable<T>> List<T> onePassSort(List<T> list) {
    if (list.size() == 0 || list.size() == 1) { 
        return list;
    } else {
        T first = list.get(0);
        T second = list.get(1);
        if (first.compareTo(second) < 0) {
            return merge(first, onePassSort(list.subList(1, list.size())));
        } else {
            return merge(second, onePassSort(merge(first, list.subList(2, list.size()))));
        }
    }
}

public static <T> List<T> merge(T head, List<T> tail) {
    List<T> result = new ArrayList<>();
    result.add(head);
    result.addAll(tail);
    return result;
}
0

Упрощенная версия с использованием Java 8 API

public static int[] bubbleSort(int[] array) {
    BiConsumer<int[],Integer> swapValueIf = (a,j) -> {
        if(a[j] > a[j+1]) {
            int temp = a[j]; 
            array[j] = a[j+1]; 
            array[j+1] = temp; 
        }
    };

    IntStream.range(0, array.length - 1).forEach( i -> IntStream.range(0, array.length - 1).forEach(j -> swapValueIf.accept(array, j)));
    return array;
}
0

Я получил правдоподобный подход:

@SuppressWarnings("unchecked") public static final <T extends Comparable<T>> List<T> declarativeBubbleSort(final List<T> list) {
    List<T> result = new ArrayList<>(list);
    int len = result.size();
    Function<Function<Object, Object>, IntConsumer> consumer =
        recur -> 
            length ->
                IntStream.range(0, length)
                         .filter(i -> IntStream.range(0, len - i - 1)
                                                 .filter(j -> result.get(j+1).compareTo(result.get(j)) < 0)
                                                 .mapToObj(j-> {
                                                     T swap = result.remove(j+1);
                                                     result.add(j, swap);
                                                     return swap;
                                                 }).count() > 0)
                         .max().ifPresent(IntConsumer.class.cast(recur.apply(Function.class.cast(recur))));
    consumer.apply(Function.class.cast(consumer)).accept(len);
    return result;
}

Я знаю, что я все еще немного поважен, но для такого рода мне трудно сделать это полностью декларативным на Java и не наказывать за производительность.

Если вы хотите быть параллельным, тогда:

@SuppressWarnings("unchecked") public static final <T extends Comparable<T>> List<T> declarativeParallelBubbleSort(final List<T> list) {
    List<T> result = new ArrayList<>(list);
    int len = result.size();
    Function<Function<Object, Object>, IntConsumer> consumer =
        recur -> 
            length ->
                IntStream.range(0, length)
                         .filter(i -> IntStream.range(0, len - i - 1)
                                                 .filter(j -> result.get(j+1).compareTo(result.get(j)) < 0)
                                                 .parallel()
                                                 .mapToObj(j-> {
                                                     synchronized(result) {
                                                         T swap = result.remove(j+1);
                                                         result.add(j, swap);
                                                         return swap;
                                                    }
                                                 }).count() > 0)
                         .max().ifPresent(IntConsumer.class.cast(recur.apply(Function.class.cast(recur))));
    consumer.apply(Function.class.cast(consumer)).accept(len);
    return result;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню