Comparison of IJDK Array and JDK ArrayList
The most heavily used class from IJDK, possibly other than Str
, is Array
. This post compares the
implementations of common idioms, using the JDK java.util.ArrayList
and
org.incava.ijdk.collect.Array
classes.
Creating an Empty Array
Array
has short syntax for creating an empty object.
ArrayList<Integer> list = new ArrayList<>();
// more explicit that the array is empty (but mutable);
// no need to use <> or <Integer>:
Array<Integer> ary = Array.empty();
Creating an Array with Elements
Arrays.asList(...)
returns an immutable ArrayList
. The IJDK Array
is always mutable, and uses
a short of
method.
// Arrays.asList returns an immutable array, so ArrayList has to wrap it:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 17, 212));
// how concise
Array<Integer> ary = Array.of(3, 17, 212);
// list : [3, 17, 212]
// ary : [3, 17, 212]
Get
As in other programming languages such as Perl and Ruby, a negative index with an array means to get
that element, starting at the end of the list. The IndexOutOfBoundsException
is not thrown, but
null
is returned instead.
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(60, 16, 252, 9, 3, 17));
Array<Integer> ary = Array.of(60, 16, 252, 9, 3, 17);
// list/ary : [60, 16, 252, 9, 3, 17]
Integer n;
n = list.size() >= 1 ? list.get(list.size() - 1) : null;
n = ary.get(-1);
// n : 17
n = list.size() >= 2 ? list.get(list.size() - 2) : null;
n = ary.get(-2);
// n : 3
n = list.size() >= 8 ? list.get(8) : null;
n = ary.get(8);
// n : null
n = list.size() > 8 ? list.get(list.size() - 8) : null;
n = ary.get(-8);
// n : null
Append (Add)
This allows the chaining of methods, for more concise code.
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 7, 23, 50));
Array<Integer> ary = Array.of(3, 7, 23, 50);
// list/ary : [3, 7, 23, 50]
list.add(2);
list.add(8);
list.add(6);
ary.append(2).append(8).append(6);
// list/ary : [3, 7, 23, 50, 2, 8, 6]
First, Last
Among the most common methods on an array are getting the first and last element, and removing them.
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(60, 16, 252, 9, 3, 17));
Array<Integer> ary = Array.of(60, 16, 252, 9, 3, 17);
// list/ary : [60, 16, 252, 9, 3, 17]
Integer n;
n = list.size() > 0 ? list.get(0) : null;
n = ary.first();
// n : 60
n = list.size() > 0 ? list.get(list.size() - 1) : null;
n = ary.last();
// n : 17
n = list.size() > 0 ? list.remove(0) : null;
n = ary.takeFirst();
// n : 60
// list/ary : [16, 252, 9, 3, 17]
n = list.size() > 0 ? list.remove(list.size() - 1) : null;
n = ary.takeLast();
// n : 17
// list/ary : [16, 252, 9, 3]
Sorting
Unlike the JDK implementation, one can create a sorted list from another, without changing the original list.
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(60, 16, 252, 9, 3, 17));
Array<Integer> ary = Array.of(60, 16, 252, 9, 3, 17);
// list/ary : [60, 16, 252, 9, 3, 17]
ArrayList<Integer> slist = new ArrayList<>(list);
Collections.sort(slist);
Array<Integer> sary = ary.sorted();
// slist/sary : [3, 9, 16, 17, 60, 252]
Unique Elements
Inspired by Ruby Array#uniq
, it is trivial to extract an Array of unique elements.
List<Integer> list = new ArrayList<>(Arrays.asList(11, 13, 11, 2, 4, 8, 11, 8));
Array<Integer> ary = Array.of(11, 13, 11, 2, 4, 8, 11, 8);
// list/ary : [11, 13, 11, 2, 4, 8, 11, 8]
List<Integer> ulist = new ArrayList<>();
for (Integer it : list) {
if (!ulist.contains(it)) {
ulist.add(it);
}
}
Array<Integer> uary = ary.unique();
// ulist/uary : [11, 13, 2, 4, 8]
Join
Joining elements into a string is easy.
List<Integer> list = new ArrayList<>(Arrays.asList(60, 16, 252, 9, 3, 17));
Array<Integer> ary = Array.of(60, 16, 252, 9, 3, 17);
// list/ary : [60, 16, 252, 9, 3, 17]
StringBuilder sb = new StringBuilder();
List<Integer> ulist = new ArrayList<>();
boolean isFirst = true;
for (Integer it : list) {
if (isFirst) {
isFirst = false;
}
else {
sb.append(", and ");
}
sb.append(String.valueOf(it));
}
String slist = sb.toString();
String sary = ary.join(", and ");
// slist/sary : 60, and 16, and 252, and 9, and 3, and 17
Plus
Array makes it simple to create a new Array from an existing array and another collection.
List<Integer> list = new ArrayList<>(Arrays.asList(60, 16, 252, 9, 3, 17));
Array<Integer> ary = Array.of(60, 16, 252, 9, 3, 17);
// list/ary : [60, 16, 252, 9, 3, 17]
List<Integer> toAdd = Arrays.asList(9, 6, 3, 1);
ArrayList<Integer> plist = new ArrayList<>(list);
plist.addAll(toAdd);
Array<Integer> pary = ary.plus(toAdd);
// plist/pary : [60, 16, 252, 9, 3, 17, 9, 6, 3, 1]
Minus
Creating an Array from an existing Array, removing those elements found in another collection.
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 8, 2, 9));
Array<Integer> ary = Array.of(3, 1, 4, 8, 2, 9);
// list/ary : [3, 1, 4, 8, 2, 9]
List<Integer> toRemove = Arrays.asList(2, 4, 6, 8);
ArrayList<Integer> mlist = new ArrayList<>(list);
mlist.removeAll(toRemove);
Array<Integer> mary = ary.minus(toRemove);
// mlist/mary : [3, 1, 9]
Intersection
A new array, containing the common elements of an array and a collection.
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 8, 2, 9));
Array<Integer> ary = Array.of(3, 1, 4, 8, 2, 9);
// list/ary : [3, 1, 4, 8, 2, 9]
List<Integer> other = Arrays.asList(2, 4, 6, 8);
List<Integer> ilist = new ArrayList<>();
for (Integer it : list) {
if (other.contains(it)) {
ilist.add(it);
}
}
Array<Integer> iary = ary.intersection(other);
// ilist/iary : [4, 8, 2]
Elements
A way to extract individual elements into a new Array
.
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 8, 2, 9));
Array<Integer> ary = Array.of(3, 1, 4, 8, 2, 9);
// list/ary : [3, 1, 4, 8, 2, 9]
List<Integer> elist = new ArrayList<>();
elist.add(list.size() > 3 ? list.get(3) : null);
elist.add(list.size() > 0 ? list.get(0) : null);
elist.add(list.size() > 2 ? list.get(list.size() - 2) : null);
elist.add(list.size() > 3 ? list.get(3) : null);
Array<Integer> eary = ary.elements(3, 0, -2, 3);
// elist/eary : [8, 3, 2, 8]
Set
The set
method dynamically resizes an array, in contrast to java.util.ArrayList#set
, which
throws an IndexOutOfBoundsException
.
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 8, 2, 9));
Array<Integer> ary = Array.of(3, 1, 4, 8, 2, 9);
// list/ary : [3, 1, 4, 8, 2, 9]
while (list.size() <= 8) {
list.add(null);
}
list.set(8, 11);
if (list.size() > 5) {
list.set(list.size() - 5, 13);
}
else {
throw new IllegalArgumentException("index: " + -5 + " is below the minimum " + -list.size());
}
ary.set(8, 11);
ary.set(-5, 13);
// list/ary : [3, 1, 4, 8, 13, 9, null, null, 11]
Get Range (Subset)
It’s simple to get a subset, using the same negative indices as get
.
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 8, 2, 9));
Array<Integer> ary = Array.of(3, 1, 4, 8, 2, 9);
// list/ary : [3, 1, 4, 8, 2, 9]
int from = 1;
int to = list.size() - 2;
List<Integer> rlist = new ArrayList<>();
for (int idx = from; idx <= to; ++idx) {
rlist.add(list.get(idx));
}
Array<Integer> rary = ary.get(1, -2);
// rlist/rary : [1, 4, 8, 2]
}
Example
Array<String> simpsons = Array.of("homer", "marge", "lisa", "bart");
// simpsons : [homer, marge, lisa, bart]
simpsons.append("grandpa").append("maggie");
// simpsons : [homer, marge, lisa, bart, grandpa, maggie]
if (simpsons.containsAny("ned", "maude")) {
}
String homer = simpsons.get(0);
// homer : homer
String maggie = simpsons.get(-1);
// maggie : maggie
String bart = simpsons.get(-3);
// bart : bart
String noone = simpsons.get(20);
// noone : null
Array<String> adults = simpsons.elements(0, 1, -2);
// adults : [homer, marge, grandpa]
Array<String> kids = simpsons.elements(2, 3, -1).plus(Array.of("nelson", "milhouse"));
// kids : [lisa, bart, maggie, nelson, milhouse]
Array<String> sorted = simpsons.sorted();
// sorted : [bart, grandpa, homer, lisa, maggie, marge]
simpsons.append("bart").append(null).append("homer").append("lisa").append(null);
// simpsons : [homer, marge, lisa, bart, grandpa, maggie, bart, null, homer, lisa, null]
Array<String> unique = simpsons.unique();
// unique : [homer, marge, lisa, bart, grandpa, maggie, null]
Array<String> nonNull = simpsons.compact();
// nonNull : [homer, marge, lisa, bart, grandpa, maggie, bart, homer, lisa]
String joined = sorted.get(0, -2).join(", ") + " and " + sorted.get(-1);
// joined : bart, grandpa, homer, lisa, maggie and marge