I recently had a discussion with a collegue why the List interface in Java doesn't have a head()
and tail()
method.
In order to implement such a functionality would have to write a wrapper that looked something like this:
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); }
I'm not aware of all List implementations but I assume that at least in LinkedList and ArrayList it should be pretty trivial to get the last and first element (constant time).
So the question is:
Is there a specific reason why it is not a good idea to provide a tail method to any List implementation?
The get() method of the ArrayList class accepts an integer representing the index value and, returns the element of the current ArrayList object at the specified index. Therefore, if you pass 0 to this method you can get the first element of the current ArrayList and, if you pass list.
Approach: Get the ArrayList with elements. Get the first element of ArrayList with use of get(index) method by passing index = 0. Get the last element of ArrayList with use of get(index) method by passing index = size – 1.
There are two methods to add elements to the list. add(E e): appends the element at the end of the list. Since List supports Generics, the type of elements that can be added is determined when the list is created. add(int index, E element): inserts the element at the given index.
Arraylist will hold the last element added at the end of the list. So it keeps the order of insertion. But it's a random access container, it doesn't really have a sense of first in first out.
The List inteface has subList
which is almost head
and tail
. You can wrap it as follows
public List head(List list) { return list.subList(0, 1); } public List tail(List list) { return list.subList(1, list.size()); }
Edit
Following the answer by @Pablo Grisafi, here is a Java quick sort implementation - not generic and not efficient. As expected head()
should return an element - not list.
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))); } }
Java Collections Framework is written by Joshua Bloch. One of his API design principles is: High power-to-weight ratio.
tail()
and head()
can be implemented by get()
and size()
, so it's not necessary to add tail()
and head()
to a very general interface java.util.List
. Once users use the methods, you don't have chance to remove them and you have to maintain these unnecessary methods forever. That's bad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With