How to assert a List in Java - java

I have two methods in a separate class in type List(). The are both returning lists , however on my test I want to assert results of both methods. Both these methods are in a Class Called navigate. My assert statement isnt working :( - I want my test to fail if the values are the same and to pass if the values are not the same
public List<Integer> methodA() {
List<Integer> overallDurationAndTimeAfterWayPoint = new ArrayList<>();
if (routeOptions.size() != 0) {
for (int i = 0; i < routeOptionDescriptions.size(); i++) {
overallDurationAndTimeAfterWayPoint.add(Integer.parseInt(routeOptionDescriptions.get(i).getText()
.replaceAll("[^\\d.]", "").trim()));
overallDurationAndTimeAfterWayPoint.add(Integer.parseInt(routeOptionTravelTimes.get(i).getText()
.replaceAll("[^\\d.]", "").trim()));
}
}
return overallDurationAndTimeAfterWayPoint;
}
public List<Integer> Method B() {
List<Integer> overallDurationAndTimeAfterWayPoint = new ArrayList<>();
if (routeOptions.size() != 0) {
for (int i = 0; i < routeOptionDescriptions.size(); i++) {
overallDurationAndTimeAfterWayPoint.add(Integer.parseInt(routeOptionDescriptions.get(i).getText()
.replaceAll("[^\\d.]", "").trim()));
overallDurationAndTimeAfterWayPoint.add(Integer.parseInt(routeOptionTravelTimes.get(i).getText()
.replaceAll("[^\\d.]", "").trim()));
}
}
System.out.println("After " + overallDurationAndTimeAfterWayPoint);
return overallDurationAndTimeAfterWayPoint;
}
Assert.assertTrue(navigate.MethodA().equals(navigate.MethodB()));

You should do
Assert.assertFalse(navigate.MethodA().equals(navigate.MethodB()));
or
Assert.assertTrue(!navigate.MethodA().equals(navigate.MethodB()));
The assertions will throw an exception when the condition is not respected, so you need to assert that the two values are not equal. In this case, if they're not equal the assertion will pass

Does order play role or not? That is something very important if you want to state if they are "same" or not.
Also I miss information what library and what version of this library are you trying to use....
Nevetheless - you still can compare those to lists as Strings.
String listAsString = list.stream()
.map(n -> String.valueOf(n))
.collect(Collectors.joining(",", "[", "]"));
that will result into [x,y,z,...] format. If order matter, you will not sort it before (also list is not best structure for something where order matters), if order does not matter - sort it first, and then compare String representations.

If you know the exact expected result, you can
compare for the expected list length
check relevant elements from the list
If order does not matter, apply some sorting first as suggested by #Smeki.

Related

Find an element from list a and b such that the sum of their values is less or equal to target and as close to target as possible

https://leetcode.com/discuss/interview-question/373202/amazon-oa-2019-optimal-utilization Given 2 lists a and b. Each element is a pair of integers where the first integer represents the unique id and the second integer represents a value. Your task is to find an element from a and an element form b such that the sum of their values is less or equal to target and as close to target as possible. Return a list of ids of selected elements. If no pair is possible, return an empty list.
question was this but I had to use Lists (like <<1,1>, <2,2> <3,3>>)
my solution was something like below. I kept failing some test cases with a NullPointerException. I am trying to find out WHAT SPECIFIC INPUT(foreground, background) COULD HAVE CAUSED THIS. (the assessment website HID the error line). the problem did not have any specifications or guarantees like 0 < deviceCapacity < 1000000, so I do NOT know what was passed in
Things I checked for:
foreground and background were not null. they did not have null values (how i checked is below)
I put a System.out.println(foregroundApplications.get(i)); System.out.println(backgroundApplications.get(j)) just before initializing "sums", the goal being to see if any values were something like null or <null, null>, but they were all valid number pairs like <1,8>. (if it was null, it would have printed null right? unsure about this). example of what I saw (there were no nulls): <1, 14> <2, 14> <3, 14> <4, 14>
i checked in the beginning if the lists (foreground and background) were null with an if(foregroundApps == null), they weren't.
I can't change my code anymore, this was an assessment with obfuscated test cases which I am trying to figure out.
P.S. If there is a better approach than O(M*N) time, I would like to know
public List<List<Integer>> optimize(int deviceCapacity, List<List<Integer> foregroundApplications, List<List<Integer>> backgroundApplications)
{
TreeMap<Integer, List<List<Integer>>> map = new TreeMap<>();
for(int i = 0; i < foregroundApplications.size(); i++)
{
for(int j = 0; j < backgroundApplications.size(); j++)
{
int sum = foregroundApplications.get(i).get(1) + backgroundApplications.get(j).get(1);
if(sum<=deviceCapacity)
{
List<List<Integer>> list= new ArrayList<>();
if(map.containsKey(sum))
{
list = map.get(sum);
}
List<Integer> pair = new ArrayList<>();
pair.add(foregroundApplications.get(i).get(0));
pair.add(backgroundApplications.get(j).get(0));
list.add(pair);
map.put(sum, list);
}
}
}
if(map.size() == 0)
{
List<List<Integer>> list= new ArrayList<>();
List<Integer> emptyPair = new ArrayList<>();
emptyPair.add(null);
emptyPair.add(null);
list.add(emptyPair);
return list;
}
return map.get(map.lastKey());
}

Iterate over one collection and get the same index value of another collection

I want know is it even possible in Java to iterate over, let say a list, and get/set the same index(int) value of other list?
for (Response e : responseList) {
e.setPrimarySkills(requestList.get(??).getPrimarySkills());
}
Since it can't be done through model mapper because of the issues, is there any neat way of doing the same ?
Using two iterators:
Iterator<Response> responseIt = responseList.iterator();
Iterator<Request> requestIt = requestList.iterator();
while(responseIt.hasNext() && requestIt.hasNext()) {
Response response = responseIt.next();
Request request = requestIt.next();
...
}
[Recommended for its clarity]
Using Guava Streams.forEachPair :
Streams.forEachPair(
requestList.stream(),
responseList.stream(),
(req, resp) -> resp.setPrimarySkills(req.getPrimarySkills())
);
Either, don't do it with a for-each loop, use an indexed for loop.
for (int i = 0; i < responseList.size(); ++i) {
responseList.get(i).setPrimarySkills(requestList.get(i).getPrimarySkills());
}
Or, use a pair of Iterators:
Iterator<Response> responseIt = responseList.iterator();
Iterator<Request> requestIt = requestList.iterator();
while (responseIt.hasNext() && requestIt.hasNext()) {
// Put responseIt.next() and requestIt.next() into variables, if you want.
responseIt.next().setPrimarySkills(requestIt.next().getPrimarySkills());
}
The advantage of Iterators over an index is that Iterators are efficient for non-RandomAccess lists; but, unless your lists are big, it's unlikely to be a significant (or even noticable) difference.
You can do it with a for-each loop, by maintaining the index yourself, but it's a bit inconsistent in the treatment of the two lists:
int i = 0;
for (Response e : responseList) {
e.setPrimarySkills(requestList.get(i).getPrimarySkills());
i++;
}
You can use a for-loop with incrementing index:
List<String> l1 = List.of("a", "b");
List<Integer> l2 = List.of(1, 2);
for(int i=0; i<l1.size(); i++) {
String s = l1.get(i);
Integer i = l2.get(i);
}
Of course you should first make sure that both lists have equal length, to avoid OutOfBounds Exception.

Properly delete duplicates in a list

Given the following datatype Testcase (XQuery, Testpath, FirstInputFile, SecondInputFile, Expected)
how can I properly delete duplicates.
Definition of duplicates:
If FirstInputFile already in the list as SecondInputFile vice versa.
Here is the Testdata
tcs.add(new HeaderAndBodyTestcase("XQ 1", "/1", "FAIL", "FAIL2", "FAILED"));
tcs.add(new HeaderAndBodyTestcase("XQ 1", "/1", "FAIL2", "FAIL", "FAILED"));
tcs.add(new HeaderAndBodyTestcase("XQ 2", "/2", "FAIL4", "FAIL3", "FAILED2"));
tcs.add(new HeaderAndBodyTestcase("XQ 2", "/2", "FAIL3", "FAIL4", "FAILED2"));
and here is the function
protected void deleteExistingDuplicatesInArrayList(final ArrayList<HeaderAndBodyTestcase> list) {
for (int idx = 0; idx < list.size() - 1; idx++) {
if (list.get(idx).firstInputFile.equals(list.get(idx).secondInputFile)
|| (list.get(idx + 1).firstInputFile.equals(list.get(idx).firstInputFile)
&& list.get(idx).secondInputFile.equals(list.get(idx + 1).secondInputFile)
|| (list.get(idx).firstInputFile.equals(list.get(idx + 1).secondInputFile)
&& list.get(idx).secondInputFile.equals(list.get(idx + 1).firstInputFile)))) {
list.remove(idx);
}
}
}
This solution is already working, but seems very crappy, so is there a better solution to this?
put everything in a Set using a comparator if necessary, and create a list from this set if you really need a List (and not a Collection)
Set<HeaderAndBodyTestcase> set = new Hashset<>(list);
Given your rather peculiar "equality" constraints, I think the best way would be to maintain two sets of already seen first- and second input files and a loop:
Set<String> first = new HashSet<>();
Set<String> second = new HashSet<>();
for (HeaderAndBodyTestcase tc : tcs) {
if (! first.contains(tc.getSecondInputFile()) &&
! second.contains(tc.getFirstInputFile())) {
first.add(tc.getFirstInputFile());
second.add(tc.getSecondInputFile());
System.out.println(tc); // or add to result list
}
}
This will also work if "equal" elements do not appear right after each other in the original list.
Also note that removing elements from a list while iterating the same list, while working sometimes, will often yield unexpected results. Better create a new, filtered list, or if you have to remove, create an Iterator from that list and use it's remove method.
On closer inspections (yes, it took me that long to understand your code), the conditions in your current working code are in fact much different than what I understood from your question, namely:
remove element if first and second is the same (actually never checked for the last element in the list)
remove element if first is the same as first on last, and second the same as second on last
remove if first is same as last second and vice versa
only consider consecutive elements (from comments)
Given those constraints, the sets are not needed and also would not work properly considering that both the elements have to match (either 'straight' or 'crossed'). Instead you can use pretty much your code as-is, but I would still use an Iterator and keep track of the last element, and also split the different checks to make the whole code much easier to understand.
HeaderAndBodyTestcase last = null;
for (Iterator<HeaderAndBodyTestcase> iter = list.iterator(); iter.hasNext();) {
HeaderAndBodyTestcase curr = iter.next();
if (curr.firstInputFile.equals(curr.secondInputFile)) {
iter.remove();
}
if (last != null) {
boolean bothEqual = curr.firstInputFile.equals(last.firstInputFile)
&& curr.secondInputFile.equals(last.secondInputFile);
boolean crossedEqual = curr.secondInputFile.equals(last.firstInputFile)
&& curr.firstInputFile.equals(last.secondInputFile);
if (bothEqual || crossedEqual) {
iter.remove();
}
}
last = curr;
}

How can I test if an array contains each value from map?

I have a map:
Map<String, String> abc = new HashMap<>();
"key1" : "value1",
"key2" : "value2"
And an array:
String[] options= {"value1", "value2", "value3"}
I am creating this array as following (I am using following method to do something else which is not relevant to the question that I am asking here):
public String[] getOptions() {
List<String> optionsList = getOptionsFromAMethod(WebElementA);
String[] options = new String[optionsList.size()];
options = optionsList.toArray(options);
return options;
}
What is the best way to verify if String[] contains each value from Map?
I am thinking about doing this:
for (Object value : abc.values()) {
Arrays.asList(options).contains(value);
}
Explanation
Your current approach creates an ArrayList (from java.util.Arrays, not to confuse with the regular ArrayList from java.util) wrapping the given array.
You then call, for each value of the map, the ArrayList#contains method. However this method is very slow. It walks through the whole list in order to search for something.
Your current approach thus yields O(n^2) which doesn't scale very well.
Solution
We can do better by using a data-structure which is designed for a fast contains query, namely a HashSet.
So instead of putting all your values into an ArrayList we will put them into a HashSet whose contains method is fast:
boolean doesContainAll = true;
HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
for (String value : abc.values()) {
if (!valuesFromArray.contains(value)) {
doesContainAll = false;
break;
}
}
// doesContainAll now is correctly set to 'true' or 'false'
The code now works in O(n) which is far better and also optimal in terms of complexity.
Of course you can optimize further to speedup by constant factors. For example you can first check the size, if options.length is greater than abc.values().size() then you can directly return with false.
JStream solution
You can also use Java 8 and Streams to simplify the above code, the result and also the procedure behind the scenes is the same:
HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
boolean doesContainAll = abc.values().stream()
.allMatch(valuesFromArray::contains);
Insights of ArrayList#contains
Let's take a closer look into java.util.Arrays.ArrayList. You can find its code here.
Here is its code for the contains method:
public boolean contains(Object o) {
return indexOf(o) != -1;
}
Lets see how indexOf is implemented:
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
So indeed, in all cases the method will traverse from left to right through the source array in order to find the object. There is no fancy method that is able to directly access the information whether the object is contained or not, it runs in O(n) and not in O(1).
Note on duplicates
If either of your data may contain duplicates and you plan to count them individually, then you will need a slightly different approach since contains will not bother for the amount of duplicates.
For this you may collect your abc.values() first into a List for example. Then, every time you checked an element, you will remove the matched element from the List.
Alternatively you can setup a HashMap<String, Integer> which counts for every element its occurrences. Then, every time you checked an element, decrease the counter by one.
You can use https://docs.oracle.com/javase/7/docs/api/java/util/List.html#containsAll(java.util.Collection)
Arrays.asList("value1", "value2", "value3").containsAll(abc.values())
I would recommend using a stream:
final List<String> optionsList = Arrays.asList(options);
abc.values().stream().allMatch(optionsList::contains);

Java - best way to compare two List<List<String>>?

What's the best way to compare the String elements of two List<List<String>>...
At the end, I want to know if they contain the same elements (true) or not (false)
This two lists I want to compare:
ObservableList<List<String>> fnlData = FXCollections.observableList(new LinkedList<>());;
List<List<String>> fnlDataTMP = new LinkedList<>();
I searched for already answered questions in the forum, but nothing helped me ..
Try fnlData.equals(fnlDataTMP) if both list are in order
or if order does not matter, try creating hash set and then compare using equals
new HashSet(fnlData).equals(new HashSet(fnlDataTMP))
I don't think there is a way that let's you achieve that out of the box.
You can do something like the functional java List.join method to quickly generate 2 Lists and compare these:
List<String> joinedFnlData = jf.data.List.join(fnlData);
List<String> joinedFnlDataTMP = jf.data.List.join(fnlDataTMP);
CollectionUtils.isEqualCollection(joinedFnlData, joinedFnlDataTMP);
Things to note:
This is probably not the cheapest operation - so it should not be invoked too often in a time critical scenario (e.g. UI thread)
It does not do a "real" equals - for that you would have to do a nested loop like in the above answer. This checks that both joined lists have the same elements with the same cardinality: e.g. if fnlData has 2 lists with "1" and "2" as the only elements and fnlDataTMP has 1 list with "1", "2" as the elements, this would mark both as equal. Depending on your scenario this might be irrelevant - if this is relevant I don't see a way around nested loops.
If by same elements you mean that the two lists are exacly the same but in a different order, then i suggest you sort the to lists and then compare them.
boolean isEqual(List<String> list1, List<String> list2) {
if (list1.size() != list2.size()) return false;
Collections.sort(list1);
Collections.sort(list2);
int i = 0;
for (String element : list1) {
if (!element.equals(list2.get(i))) return false;
i++;
}
return true;
}
I didn't test it yet!
For a Collections (Lists) to be equal, both need to be a proper subset of each other. Thus list1.containsAll(list2) and list2.containsAll(list1).
For a List within a List, you will have to loop, but that's essentially what any built-in library has to do anyway.
looks like you need a double iteration
boolean checkEqual(List<List<String>> l1,List<List<String>> l2){
if(l1.size() != l2.size()){
return false;
}
if(l1.hashCode() != l2.hashCode()){
return false;
}
for(int i=0; i<l1.size(); i++) {
List<String> curr = l1.get(i);
List<String> comp = l2.get(i);
if(curr.size() != comp.size()){
return false;
}
if(curr.hashCode() != comp.hashCode()){
return false;
}
for(int j=0; j<curr.size(); j++) {
if(!curr.get(j).equals(comp.get(j))){
return false;
}
}
}
return true;
}
You can improve the solution checking first difference of hashCode
if(l1.hashCode() != l2.hashCode()){
return false;
}
if hashCode are equal, then check eventually deep difference
I came up with a solution that doesn't need to have two inner loops by using Collections.sort(List list), which sorts a List in place, and List.containsAll(java.util.Collection), which compares two Lists for their elements.
Sample Code:
//Creating two lists for comparison and their inner lists
List<List<String>> list1 = new LinkedList<>();
List<List<String>> list2 = new LinkedList<>();
LinkedList<String> l11 = new LinkedList<>();
l11.add("a");
l11.add("b");
l11.add("c");
LinkedList<String> l12 = new LinkedList<>();
l12.add("d");
l12.add("e");
l12.add("f");
LinkedList<String> l21 = new LinkedList<>();
l21.add("b");
l21.add("c");
l21.add(new String("a"));
LinkedList<String> l22 = new LinkedList<>();
l22.add("d");
l22.add("e");
l22.add("f");
list1.add(l11);
list1.add(l12);
list2.add(l22);
list2.add(l21);
for (List<String> list : list1){
Collections.sort(list);
}
for (List<String> list : list2){
Collections.sort(list);
}
System.out.println(list1.containsAll(list2) && list2.containsAll(list1)); //prints true
If you don't want to change the order of the elements in the inner Lists you can create copies of the outer Lists and perform the operations on them.
Note: This only works for sortable collections.
Store one of the list in a HashMap and then iterate through the other list and check if the Map already contains that KEY. Ofcourse you have to ensure that KEY types match.

Categories