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

Related