hamcrest: how to match array is subset of another array? - java

Given that:
int[] a = {1, 2, 3, 4};
int[] b = {1, 2, 3, 4, 5};
How to asser that "a" is a subset of "b" using hamcrest matchers?
The following works
assertThat(Arrays.asList(b), hasItems(a));
But since I am creating "a" from "b", I would prefer to apply the asserts on "a" as the value.
Something like
assertThat(a, isSubsetOf(b));
Additionally it is preferable to avoid converting the array to a list.

You can use a combination of the Every and IsIn matcher:
assertThat(Arrays.asList(a), everyItem(in(b)));
This does check if every item of a is contained in b. Make sure a and b are of type Integer[] otherwise you might get unexpected results.
If you are using an older version of hamcrest (for example 1.3) you can use the following:
assertThat(Arrays.asList(a), everyItem(isIn(b)));
In the latest version isIn is deprecated in favor of in.

Create your own custom matcher by extending org.hamcrest.TypeSafeMatcher and use it in the assertThat() method. You can refer the code of org.hamcrest.collection.IsArrayContaining and create your own matcher

If assertj is an option for you:
assertThat(b).contains(a); // order doesn't matter
assertThat(b).containsSequence(a); // order matters

Related

How can I loop through and Sort a nested List based on the First element of each sub-Lists

For example:
a = [jamie, 3, 5, NY]`
b = [Barney, 2, 3, FL]
c = [Thomas, 4, 6, TX]
d = [Darnell, 5, 6, NC]
unsortedArrayList = [ [jamie, 3, 5, NY], [Barney, 2, 3, FL], [Thomas, 4, 6, TX], [Darnell, 5, 6, NC] ]
I want to loop through the unsortedArrayList input and sort it by the first element of each sub-list such that the output will be:
sortedArrayList = [ [Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX] ]
so far, I have looped through the unsorted list:
for(ArrayList<String> s : unsortedList)
How can I implement sorting?
I would greatly appreciate any clearly written out implementations on how to sort this list, because I'm not exactly sure how to go about it.
Everything you need to solve this problem is to define a comparator that will establish the order of lists of String based on the first element and comparison should be case-insensitive (because you've specified in the example that "jamie" should appear before "Thomas").
The fluent way to define a comparator is to make use of static methods introduced with Java 8, in this case we can utilize comparing(function, Comparator):
Comparator<List<String>> comparator =
Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER);
The first argument keyExtractor function defines how to extract to extract the sorting key from the given element. And the second argument denotes the comparator that needs to be used to compare the key, in this comparator CASE_INSENSITIVE_ORDER accessible as a static field in the String class.
For more information on how to build Comparators using Java 8 method have a look at this tutorial.
You can also define this comparator inline (it depends on how frequently it'll be required to sort the incoming lists). And if it's not necessary to preserve the initial form of the unsorted list, it could be done by applying method sort() (also added with Java 8) on the list:
unsorted.sort(Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER));
System.out.println(unsorted);
Will produce the output:
[[Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX]]
Otherwise, if you need to preserve the unsorted list intact, you can create a copy of the list sort it as shown above or you can make use of Stream API to generate a new sorted list:
List<List<String>> sortedByFirstElement = unsorted.stream()
.sorted(Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER))
.collect(Collectors.toList()); // or .toList() with Java 16+
Will give the output:
[[Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX]]
Have a look at these tutorials provided by Oracle for more information on lambda expressions and streams.
You play around with this Demo Online.
Sidenote: it seems like each list contains the personal data. If so consider defining a class (like Person, or Employee, etc.), because storing the object data in a collection is an antipattern. Classes provide a structure to the data, ability to use appropriate types for each value, and convenient access via methods with self-explanatory names instead of faceless get(0).
If you want to sort the original list (which means everything in your list will be in a different place and you lose the original order) then use the sort method:
unsortedArrayList.sort((a, b) -> a.get[0].compareTo(b.get(0)));
If you want to create a new sorted list, leaving the original list unchanged:
var sortedList = new ArrayList<>(unsortedArrayList);
sortedList.sort((a, b) -> a.get[0].compareTo(b.get(0)));
or use Streams:
var sortedList = unsortedArrayList.stream()
.sorted((a, b) -> a.get[0].compareTo(b.get(0)))
.toList();
In each case, the argument to the sort or sorted method is a Comparator which takes the two sublist arguments and compares the first element of each.

How to find if all elements of list are in a set in Java 8?

While it is easy to do it in a for loop, is there a way in Java-8 to find if all elements in list L are present in Set s ?
There's no need to use a Stream for this when you can use Set#containsAll:
var set = Set.of(1, 2, 3, 4, 5);
var list = List.of(2, 3, 4);
System.out.println(set.containsAll(list));
Output:
true
You can use allMatch:
boolean result = l.stream().allMatch(s::contains);
Yes.
long commonElements = l.stream().filter(s::contains).count();
if (commonElements == l.size()) {
//do something
}
Sets are nice because they are built for exactly this kind of thing: checking if an item exists already. Lists are not as good at this practice, but are good for quick traversal. So, you want to loop through the list and compare each element to the set, vs the other way around.
Streams are a nice resource for performing operations in-line vs explicitly breaking things out.
EDIT: #Aomine 's answer is better than mine
boolean result = myList.stream().allMatch(mySet::contains);

List of unique lists in java

I need to create a collection of unique collection in java. Could someone please suggest possible containers for the same.
I want to have something like List<List<int>> where each each of the list could repeat itself in terms of its contents.
For example if my current state of the parent list is say
[ [1,2,3], [3,4,5], [4,5,6] ] and if I intend to add another list say [3,4,5] to it, it should not be duplicated and should not be added.
contains() method of List will work with integers, floats etc, but I am not sure if it will be able to match lists.
Please suggest any other container which could help.
Thanks.
You'll probably be best off using Set<List<Integer>> instead of List<List<Integer>>.
The above applied to your example:
Set<List<Integer>> uniqueLists = new HashSet<>();
uniqueLists.add(Arrays.asList(1, 2, 3));
uniqueLists.add(Arrays.asList(3, 4, 5));
uniqueLists.add(Arrays.asList(4, 5, 6));
// Now, this won't be added:
uniqueLists.add(Arrays.asList(3, 4, 5));
Be careful when you put a collection inside a set, though. You should not change it again, after you have put it in the set.
Perhaps you would be interested to use Set<Set<Integer>>.
In case you would like to maintain the addition order, you can use LinkedHashSet.
Your code will be like
Set<Set<Integer> uniqueLists = new LinkedHashSet<Set<Integer>>();
uniqueLists.add(new LinkedHashSet(Arrays.asList(1, 2, 3)));
It would avoid two problems from using Set<List<Integer>>.
1) It would retains addition order of the individual lists
2) It individual list will also not have duplicate integer entries.

Implicit Type Conversion?

I am reviewing someone else's Grails code and I see the following:
Set<Integer> weeks = new ArrayList<Integer>()
It looks like after this line is set, Grails thinks that weeks is a HashSet. I am not well versed in either Java or Grails, and the (java) documentation looks like ArrayList extends List and HashSet extends Set, but that this direct construction wouldn't work. Is this a Grails thing? Thanks.
It's somewhat unusual in Groovy to see new ArrayList<Integer>() since [] works identically and is way less verbose, so I would have written that as Set<Integer> weeks = []. Then it's a bit more clear what's going on - Groovy is converting one collection type to another, with the [] really as a convenient way to create a holder and populate the initial data (if there is any). Since there's no syntactic sugar for collections other than [] for List and [:] you need these conversions.
def weeks = [] as Set is probably the more common syntax. This is also more clear since [] is just temporary and using "as" does the conversion, and more explicitly than just declaring the type on the left side.
You can also use this to convert collections to arrays. You can't use Java syntax to create arrays since it uses braces and looks like a Closure definition, so instead of int[] numbers = new int[] { 1, 2, 3 } you have to do int[] numbers = [1, 2, 3] or def numbers = [1, 2, 3] as int[].

How do I define an array with multiple values?

I am doing some Junit testing on my code, which is meant to produce an arraylist of n prime numbers. I want to compare the created list to a list of known prime numbers in an array, and to do this I need to insert multiple values into an array in my testing class.
So what I have at the moment is
int knownPrimes[] = new int[50];
I know that I could insert values into this array by typing
knownPrimes[1] = 2;
knownPrimes[2] = 3;
etc etc.
I was just wondering how I would do this all in one big chunk, maybe something like:
knownPrimes[] = {2,3,5,7,9...};
but I am not sure of the syntax and I can't find anything on google. Would anyone be able to help me out please ?
Thanks a lot.
int[] knownPrimes = new int[] {2, 3, 5, 7, 9};
As Peter mentioned, the new int[] can be omitted.
try
int[] knownPrimes = {2,3,5,7,9};
or
int[] knownPrimes;
knownPrimes = new int[] {2,3,5,7,9}
I agree with the solutions posted.
A good book is Thinking in Java, by Bruce Eckel. He covers initialization in Chapter 4, "Initialization and Cleanup," and uses Peter's method. You may buy the latest edition or download an older edition for free.
If the list of knownPrimes is not going to be subclassed, you might want to add the keyword final. If it is class variable and you do not want the value to change after the initialization, you might want to add the keyword static. (I suspect that the list of known primes will be the same throughout the execution of the program.) If you want to access the length of the array, use knownPrimes.length.
Oh, and by the way, 9 should not be in the list of knownPrimes.

Categories

Resources