2016-10-30 4 views
1

Итак, я читаю на Java, и я натолкнулся на пример. Я понятия не имею, как это работает. Ниже вы увидите метод sortByTime() в классе ConsLoRunner. Мой вопрос в том, как он может что-то выводить, не будет ли он снова и снова повторять этот метод и никогда не достигнет метода insertByTime(this.first)?Невозможно понять метод вызова Java по методу

Боковое примечание: пример Бегунов для марафона и их сортировка в зависимости от их времени (от самого быстрого до самого медленного).

class Runner { 
    String name; 
    int age; 
    int bib; 
    boolean isMale; 
    int pos; 
    int time; 

    Runner(String name, int age, int bib, boolean isMale, int pos, int time) { 
     this.name = name; 
     this.age = age; 
     this.bib = bib; 
     this.isMale = isMale; 
     this.pos = pos; 
     this.time = time; 
    } 

    public boolean finishesBefore(Runner r) { 
     return this.time < r.time; 
    } 
} 

interface ILoRunner { 
    ILoRunner sortByTime(); 
    ILoRunner insertByTime(Runner r); 
} 

class MtLoRunner implements ILoRunner { 

    public ILoRunner sortByTime() { 
     return this; 
    } 

    public ILoRunner insertByTime(Runner r) { 
     return new ConsLoRunner(r, this); 
    } 

} 

class ConsLoRunner implements ILoRunner { 
    Runner first; 
    ILoRunner rest; 

    ConsLoRunner(Runner first, ILoRunner rest) { 
     this.first = first; 
     this.rest = rest; 
    } 
    /*******HOW DOES IT DO THIS?????**********/ 
    public ILoRunner sortByTime() { 
     return this.rest.sortByTime().insertByTime(this.first); 
    } 

    public ILoRunner insertByTime(Runner r) { 
     if (this.first.finishesBefore(r)) { 
      return new ConsLoRunner(this.first, this.rest.insertByTime(r)); 
     } 
     else { 
      return new ConsLoRunner(r, this); 
     } 
    } 
} 

class ExamplesRunners { 
    MtLoRunner empty = new MtLoRunner(); 
    Runner tim = new Runner ("Tim", 1, 2, true, 5, 6); 
    Runner bob = new Runner ("Bob", 5, 6, true, 9, 50); 
    Runner jim = new Runner ("Jim", 5, 6, true, 10, 40); 

    ILoRunner list1 = new ConsLoRunner(this.tim, new ConsLoRunner(this.bob, new ConsLoRunner(this.jim, this.empty))); 

    boolean testSort(Tester t) { 
     return t.checkExpect(this.list1.sortByTime(), new ConsLoRunner(this.tim, new ConsLoRunner(this.jim, new ConsLoRunner(this.bob, this.empty)))); 
    } 
} 

ответ

1

Я понятия не имею, как это работает.

Я постараюсь ответить на этот вопрос.

Вы ищете (довольно запутанную) версию Java List Data Structure, которая обычно встречается на таких языках, как LISP.

«Список» в нашем случае может быть определен рекурсивно. Это либо:

  • Пустой список, обозначаемый () или nil или
  • Первый элемент, затем другой список (остальные элементы): (first, rest)

Как вы можете видеть , есть четкое отображение ваших Java-классов для этих понятий:

ILoRunner -> An abstract List, the root type 
MtLoRunner -> An empty list:() or nil 
ConsLoRunner -> A non-empty list: (first, rest) 

ключ находится в начале го e имя ConsLoRunner. В LISP cons является «конструктором», который создает объект, содержащий еще два объекта. cons часто используется для создания списков. Но он также может использоваться для создания структур, не являющихся списками. Извините, я отвлекся.

Переписывая ваш пример в представление списка, список бегунов list1 выглядит примерно так (опуская другие поля для простоты):

(Tim <-- first: Tim, rest: (Bob ...) 
    (Bob <-- first: Bob, rest: (Jim()) 
     (Jim()))) <-- first: Jim, rest:() // rest of the list is empty, no more elements. 

Именно то, что ExamplesRunners делает.

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

  1. Первый сорт остальная часть списка
  2. Затем вставить первый элемент в отсортированном списке в шаге один

Это какой ConsLoRunner.sortByTime делает. Но заметьте, что он возвращает новый, отсортированный список. Таким образом, первоначальный список не изменяется.

Чтобы вставить элемент x в отсортированный список также прост:

  1. Сравнить x с первым элементом списка
  2. If x меньше, вставить x перед всем списком
  3. В противном случае вставьте x в остальную часть списка

Имейте в виду, что вставка выполняется путем создания нового объекта cons с соответствующим порядком элементов. И снова исходный список сохраняется.

IMO, код будет намного легче читать, если бы он был написан против интерфейса фактического списка, вместо того, чтобы смешивать его с внутренним представлением и конструированием новых списков.

// The list interface 
interface List<T extends Comparable<T>> { 

    boolean isEmpty(); 

    T first(); 

    List<T> rest(); 
} 

// Instances of this class represents an empty list:() 
class Empty<T extends Comparable<T>> implements List<T> { 

    @Override 
    public boolean isEmpty() { 
     return true; 
    } 

    @Override 
    public T first() { 
     return null; 
    } 

    @Override 
    public List<T> rest() { 
     return null; 
    } 

    @Override 
    public String toString() { 
     return "()"; 
    } 
} 

// A non-empty list, composed of the first element and the rest. 
class Cons<T extends Comparable<T>> implements List<T> { 

    private final T first; 
    private final List<T> rest; 

    public Cons(T first, List<T> rest) { 
     this.first = first; 
     this.rest = rest; 
    } 

    @Override 
    public boolean isEmpty() { 
     return false; 
    } 

    @Override 
    public T first() { 
     return first; 
    } 

    @Override 
    public List<T> rest() { 
     return rest; 
    } 

    @Override 
    public String toString() { 
     return "(" + first +", " + rest + ")"; 
    } 
} 

public class Lisp { 

    // Creates and returns a sorted list from the given list 
    // The original list is never changed. 
    public static <T extends Comparable<T>> List<T> sort(List<T> list) { 
     if (list.isEmpty()) { 
      // Empty lists are already sorted. 
      return list; 
     } else { 
      // We first sort the rest of the list 
      List<T> sortedRest = sort(list.rest()); 
      // Then insert the first element into the sorted list 
      return insert(list.first(), sortedRest); 
     } 
    } 

    // Creates and returns a sorted list with x inserted into a proper position in the already sorted list 
    private static <T extends Comparable<T>> List<T> insert(T x, List<T> list) { 
     if (list.isEmpty() || x.compareTo(list.first()) < 0) { 
      return new Cons<>(x, list); 
     } else { 
      // Recursive call return a sorted list containing x 
      return new Cons<>(list.first(), 
           insert(x, list.rest())); 
     } 
    } 

    public static void main(String [] args) { 
     List<Integer> alist = new Cons<>(7, new Cons<>(1, new Cons<>(4, new Empty<>()))); 
     System.out.println("Sorted: " + sort(alist)); 
     System.out.println("Original: " + alist); 
    } 
} 

ВЫВОД

Sorted: (1, (4, (7,()))) 
Original: (7, (1, (4,()))) 
+0

Это было потрясающе, спасибо вам большое. Одна часть, о которой я до сих пор смущаюсь, - это то, как Java знает «1. Сортировка остальной части списка. Все, что вы делаете, это вызов метода в остальной части списка? Как это волшебно просто сортировать? – CtrlAltDelete

+0

А это красота рекурсии, не так ли? Сначала вы определяете базовый регистр для пустого списка. Затем в каждой рекурсии вы даете методу меньшую проблему и считаете, что решение, которое оно возвращает вам, является правильным, а затем действовать по решению, чтобы получить более крупное решение. Я постараюсь объяснить это лучше. :) –

0

не он просто рекурсию этот метод снова и снова

Нет, это не с помощью рекурсии вообще, потому что это вызов метода класса члена rest:

верните это. rest .sortByTime(). InsertByTime (это.первый);

+0

И если он не использует рекурсию, что является точкой ввода '.sortByTime()' в ответном заявлении? – CtrlAltDelete

+0

Просьба [прочитать это] (https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html) для получения информации о переменных. Точка использования 'sortByTime()' в возврате - это вызов этого метода, предположительно для сортировки данных, содержащихся в этом объекте, перед возвратом результата. –

Смежные вопросы