无法理解方法上的Java调用方法

时间:2016-10-30 22:27:19

标签: java

所以我正在阅读Java,我遇到了一个例子。我不知道它是如何工作的。您将在下面看到sortByTime()课程中的方法ConsLoRunner。我的问题是它是如何输出一些东西的,它不会一遍又一遍地递归那种方法,而且永远不会达到insertByTime(this.first)方法?

旁注:示例是马拉松的跑步者,并根据他们的时间(最快到最慢)对他们进行排序。

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))));
    }
}

2 个答案:

答案 0 :(得分:0)

  

不会一遍又一遍地递归那种方法

不,它根本没有使用递归,因为它在类成员rest上调用方法:

返回此。休息 .sortByTime()。insertByTime(this.first);

答案 1 :(得分:0)

  

我不知道它是如何运作的。

我会试着回答这个问题。

您正在查看List Data Structure的(非常令人困惑的)Java版本,该版本通常位于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)

线索位于名称ConsLoRunner的开头。在LISP中,cons是一个“构造函数”,它创建一个包含另外两个对象的对象。 cons通常用于创建列表。但它也可以用于创建非列表结构。对不起,我离题了。

将您的示例重写为列表表示,\ n \ n 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. 然后将第一个元素插入到第一步的排序列表中
  3. 这是ConsLoRunner.sortByTime正在做的事情。但请注意,它正在返回一个新的排序列表。 因此原始列表永远不会更改。

    将元素x插入到排序列表中也很简单:

    1. x与列表的第一个元素进行比较
    2. 如果x较小,请在整个列表
    3. 之前插入x
    4. 否则,请将x插入列表的其余部分
    5. 请记住,插入是通过创建一个具有适当元素顺序的新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, ())))