为什么List中没有tail()或head()方法来获取last或first元素?

lei*_*ifg 22 java api list

我最近与同事讨论了为什么Java中的List接口没有head()tail()方法.

为了实现这样的功能,必须编写一个看起来像这样的包装器:

public E head() {
 if (underlyingList == null || underlyingList.isEmpty())
  return null;

 return underlyingList.get(0);
}


public E tail() {
 if (underlyingList == null || underlyingList.isEmpty())
  return null;

 return underlyingList.get(underlyingList.size()-1);
}
Run Code Online (Sandbox Code Playgroud)

我不知道所有的List实现,但我认为至少在LinkedList和ArrayList中,获取最后一个元素(常量时间)应该是非常简单的.

所以问题是:

是否有一个特定的原因为什么为任何List实现提供tail方法不是一个好主意?

Dav*_*oko 19

列表接口subList几乎headtail.你可以按如下方式包装它

public List head(List list) {
    return list.subList(0, 1);
}

public List tail(List list) {
    return list.subList(1, list.size());
}
Run Code Online (Sandbox Code Playgroud)

编辑

根据@Pablo Grisafi的回答,这是一个Java快速排序实现 - 不是通用的,也不是高效的.正如所料,head()应该返回一个元素 - 而不是列表.

public class QSort {

    public static List<Integer> qsort(List<Integer> list) {
        if (list.isEmpty()) {
            return list;
        } else {
            return merge(
                    qsort(lesser
                            (head(list), tail(list))),
                    head(list),
                    qsort(greater(
                            head(list), tail(list)))
            );
        }
    }

    private static Integer head(List<Integer> list) {
        return list.get(0);
    }

    private static List<Integer> tail(List<Integer> list) {
        return list.subList(1, list.size());
    }

    private static List<Integer> lesser(Integer p, List<Integer> list) {
        return list.stream().filter(i -> i < p).collect(toList());
    }

    private static List<Integer> greater(Integer p, List<Integer> list) {
        return list.stream().filter(i -> i >= p).collect(toList());
    }

    private static List<Integer> merge(List<Integer> lesser, Integer p, List<Integer> greater) {
        ArrayList list = new ArrayList(lesser);
        list.add(p);
        list.addAll(greater);

        return list;
    }

    public static void main(String[] args) {
        System.out.println(qsort(asList(7, 1, 2, 3, -1, 8, 4, 5, 6)));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不应该"头"返回元素而不是子列表?即`public <T> T head(List <T> list){return list.get(0); }` (11认同)
  • 最后,有人知道`tail()`应该是什么. (3认同)
  • 如果您认为在空列表上调用head/tail是例外,欢迎您抛出异常.但请注意,许多列表处理习惯用法(尤其是递归/功能)认为这种情况完全有效. (2认同)

卢声远*_* Lu 18

Java Collections Framework由Joshua Bloch编写.他的API设计原则之一是:高功率重量比.

tail()并且head()可以通过get()和实现size(),因此没有必要添加tail()head()非常通用的接口java.util.List.一旦用户使用这些方法,您就没有机会删除它们,您必须永远保留这些不必要的方法.那很糟.

  • 事情是这些方法不是不必要的 - 功能样式列表处理是没有这些的PITA. (21认同)
  • 不仅仅是PITA,它的用处也就不那么重要了.假设我有一个懒惰的列表,我想得到它的尾巴.我该怎么办?此外,为了得到列表的尾部,我必须走所有它来计算长度.那是很多浪费. (2认同)

Kev*_*ong 5

如果你想递归地处理一个列表,这通常是函数式编程中使用的头/尾,你可以使用迭代器。

Integer min(Iterator<Integer> iterator) {
    if ( !iterator.hasNext() ) return null;
    Integer head = iterator.next();
    Integer minTail = min(iterator);
    return minTail == null ? head : Math.min(head, minTail);
}
Run Code Online (Sandbox Code Playgroud)