As a brief note today, I was working on a Java/Android application recently, and I needed a “tail” function when I was working on a Java list. What I mean is that Scala has a tail
function that returns all elements of the list except for the head element, like this:
scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)
scala> x.tail
res1: List[Int] = List(2, 3, 4) //head element removed
and I wanted the same thing in Java.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
A Java list `tail` function
The short answer is that lists in Java 6/7/8 don’t have a tail
method, so I wrote my own tail
function to work on List
, ArrayList
, LinkedList
, etc:
/**
* WARNING/TODO: this method doesn’t check the list size, so you better
* be sure it contains at least one element.
*/
public static <T> List<T> tail(List<T> xs)
throws IndexOutOfBoundsException, IllegalArgumentException {
return xs.subList(1, xs.size());
}
If the generics in that code make your eyes water, here’s a non-generic version of that function that works on a list of integers:
public static List<Integer> tail(List<Integer> xs)
throws IndexOutOfBoundsException, IllegalArgumentException {
return xs.subList(1, xs.size());
}
I put that method in a class named ListUtils that has a bunch of other list utility functions that I like/need.
As the comment on the tail
function implies, this is a potentially dangerous method. subList
specifically can throw these exceptions:
IndexOutOfBoundsException
IllegalArgumentException
See my Java List subList examples for a little more information on the subList
method. You might want to handle a null
list of empty list in your own code, but when I thought, “What is the tail of an empty list,” I thought the answer to that question was undefined; returning an empty list is not accurate, so I let subList
explode.
A `tail` function example
Here’s an example of how I use this tail
function:
import static com.alvinalexander.utils.ListUtils.tail;
// later ...
if (penalty == 1) {
return tail(listOfPossiblePlayResults); // rm the head element
}
In that example, this code:
return tail(listOfPossiblePlayResults)
returns a new list with the head element of the list removed if the penalty
is 1
.
More `tail` documentation
I’m just throwing this tail
function out here quickly today, but if you want to know more about how it works, here’s some example code that helps to demonstrate how it works (and fails) with several different use cases:
import java.util.*;
public class TailFunction {
public static void main(String[] args) {
List<String> x = new ArrayList<>();
x.add("a");
x.add("b");
x.add("c");
System.out.println(tail(x)); // [b,c]
List<String> y = new ArrayList<>();
y.add("a");
System.out.println(tail(y)); // []
// an exmpty list throws an exception
List<String> z = new ArrayList<>();
System.out.println(tail(z)); // IllegalArgumentException: fromIndex(1) > toIndex(0)
}
public static <T> List<T> tail(List<T> xs)
throws IndexOutOfBoundsException, IllegalArgumentException {
return xs.subList(1, xs.size());
}
}
A Java List `head` function
As a brief related note, I haven’t tested this code, but a Java List head function should look like this:
public static <T> List<T> head(List<T> xs) throws IndexOutOfBoundsException, IllegalArgumentException { return xs.subList(0, 1); }
I know this might not seem like much to Java OOP developers, but when you use head/tail functions like this all the time in languages like Scala, you sure do miss them when you work with Java.
Summary
In summary, if you need a tail
function that works on a Java list — such as an ArrayList
or LinkedList
— I hope this example and source code is helpful. Also note that if you don’t want to have to create your own “list utilities” library, there are other libraries in existence, such as the Apache Commons library.