Utility Functions: Arrays and Collections
Steven J. Zeil
Between our exploration of arrays, ArrayList
, and LinkedLink
in this module and our look at some common functions in our look at worst case analysis in the previous module, we’ve accumulated a fair number of “utility” functions for doing things like searching and inserting into sequences.
A number of these are already available to us as Java programmers, however, via the classes java.util.Arrays
and java.util.Collections
.
You should become familiar with some of these so that you avoid “reinventing the wheel” when writing your own code.
java.util.Arrays
provides utility functions for working with ordinary arrays.java.util.Collections
provides utilities for working withList
and other Java collections.
1 Searching sequences
1.1 Sequential search
We have previously discussed the sequential search algorithm.
If you aren’t working with arrays, the List
class provides the indexOf
function that implements a sequential search:
List<String> names = ...;
⋮
int k = names.indexOf(myName);
if (k >= 0) {
System.out.println("myName is in the list at position " + k);
} else {
System.out.println("myName is not in the list.");
}
list.indexOf(data)
is O(list.size()).
As far as I know, there is no built-in sequential search function for arrays.
1.2 Binary search
We have seen that, if our data is sorted, then binary search can be much faster than sequential.
This is available both for arrays:
String[] names = new String[N];
⋮
int k = java.util.Arrays.binarySearch(names, myName);
The above call is O(lognames.length).
and for List
s:
List<String> names = ...
⋮
int k = java.util.Collections.binarySearch(names, myName);
The above call is O(lognames.size()) if
names
is anArrayList
, but is O(names.size()) ifnames
is anLinkedLost
.
- The
Arrays
form of binary search has variations that allow you to supply a starting and ending position within the array, useful if the array is actually longer than the amount of data it holds. - The
Collections
form of binary search has variations that allow you to supply aComparator
to compare elements if needed.
1.2.1 Importing
You can use an import
statement to shorten the function names.
import java.util.Arrays;
import java.util.Collections;
This would allow you to write simple Arrays.binarySearch
and Collections.binarySearch
.
You can shorten things even further to just say binarySearch
with
import static java.util.Arrays.binarySearch;
import static java.util.Collections.binarySearch;
All of the functions in Arrays
and Collections
are static
, and that needs to be stated explicitly in the import.
1.2.2 The insertion point
The return value from binarySearch
is rather interesting.
int k = binarySearch(names, myName);
- If
binarySearch
finds the values in the array or list, `k
will be nonnegative (zero or positive) and is the position at which the data was found. - If
binarySearch
does not find the value, it returns a negative value,(-(insertion point) - 1)
, whereinsertionPoint
is where you would want to insert the value in order to keep the array or list sorted.
List<String> names = ...
⋮
int k = binarySearch(names, myName);
if (k < 0) {
int insertionPoint = - (k + 1);
names.add(insertionPoint, myName);
}
Keep in mind, though, that the add
at a position function is O(names.size()), which rather wastes some of the logarithmic speed of the binarySearch
itself.
2 Copying sequences
For arrays, you can create a copy with copyOf
:
String[] array = ...
⋮
String[] array2 = Arrays.copyOf(array, newLength);
For List
s and other collections, you can use addAll
to copy an array:
Collections.addAll(names, array);
or copy
to copy from another collection:
Collections.copy(names, anotherList);
An important distinction:
addAll
appends elements onto the end of the existing list.copy
overwrites the elements already present in the existing list.
Both operations are O(N) where N is the number of items being copied.
3 Rearranging sequences
3.1 Swapping elements
You can exchange elements in a list like this:
Collections.swap(names, i, j);
This is O(1) if the list is an
ArrayList
, but O(list.size()) forLinkedList
s.
3.2 Reversing
You can reverse the order of elements in a list:
Collections.reverse(names);
3.3 Sorting
or you can sort them into order:
Collections.sort(names);
You can also sort arrays:
Arrays.sort(array);
3.4 Shuffling
or you can rearrange them at random:
Collections.shuffle(names);
4 Converting
You can convert between arrays and lists:
List<String> list = ...
String[] array = ...
List<String> list2 = Arrays.asList(array);
String[] array2 = list.toArray(new String[0]); // Not a Collections function.
- The parameter to the
toArray
function is a bit odd, but necessary becausetoArray
is actually a generic and needs to know what type of array to produce. - The
asList
function is actually quite flexible. You cna use it with individual elements as well as with an array. E.g.,List<String> vowels = Arrays.asList("A", "E", "I", "O", "U");
-
The list returned by
asList
is neitherArrayList
norLinkedList
.
5 Comparing Arrays
You can compare arrays like this:
int result = Arrays.compare(array1, array2);
This is a lexicographic comparison.
- The result will be negative if the first first nonequal elements occur in position
i
andarray1[i] < array2[i]
(or, for arrays of objects, ifarray1[i].compareTo(array2[i]) < 0
). - The result will be positive if the first first nonequal elements occur in position
i
andarray1[i] > array2[i]
(or, for arrays of objects, ifarray1[i].compareTo(array2[i]) > 0
). - If no pair of corresponding elements are non-equal, the result is 0 if the arrays have the same length, negative if
array1
is shorter thanarray2
, or positive ifarray1
is longer.
There is no similar compare
function in Collections
. However, remember that lists and all other collections do provide an equals
function. If you want a full-fledged compareTo
for a collection, though, you would need to write it yourself.