private static Iterable<Object> iterable(
final Object first, final Object second, final Object[] rest) {
checkNotNull(rest);
return new AbstractList<Object>() {
@Override
public int size() {
return rest.length + 2;
}
@Override
public Object get(int index) {
switch (index) {
case 0:
return first;
case 1:
return second;
default:
return rest[index - 2];
}
}
};
}
What is author's purpose?
I guess he wants to make use of the array generated by compiler, rather than new an ArrayList.
But still a confusing point, why not write as below?
private static Iterable<Object> iterable(final Object[] rest) {
checkNotNull(rest);
return new AbstractList<Object>() {
@Override
public int size() {
return rest.length;
}
@Override
public Object get(int index) {
return rest[index];
}
};
}
The point here is that this method is called from public methods which look like (source):
public final String join(
@NullableDecl Object first, @NullableDecl Object second, Object... rest) {
return join(iterable(first, second, rest));
}
Using signatures like this is a trick to force you to pass in at least two arguments - after all, if you've not got two arguments, there is nothing to join.
For example:
Joiner.on(':').join(); // Compiler error.
Joiner.on(':').join("A"); // Compiler error.
Joiner.on(':').join("A", "B"); // OK.
Joiner.on(':').join("A", "B", "C"); // OK.
// etc.
This iterable
method just creates an Iterable
without having to copy everything into a new array. Doing so would be O(n)
in the number of arguments; the approach taken here is O(1)
.