Use method to compare lists - java

I'm trying to use a method to compare t2o different lists. Basically I want to pass two different lists to a method which will return true or false if the elements of one array list are contained in the other using .contains. Right now it only returns true - and I'm not sure why. I'd like it to return false. If someone could help me figure this out, that would be great.
public class ArrayListTest {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
list1.add("cat");
list1.add("dog");
list1.add("zebra");
list1.add("lion");
list1.add("mouse");
//Test Values
//list2.add("cat");
list2.add("lizard");
boolean doesitcontain = contains(list1, list2);
System.out.println(doesitcontain);
}
public static boolean contains (List<String>list1, List<String>list2){
boolean yesitcontains;
for(int i = 0; i < list1.size(); i++){
if(list2.contains(list1.get(i))){
System.out.println("Duplicate: "+list1.get(i));
yesitcontains = true;
System.out.println(yesitcontains);
}else{
yesitcontains = false;
System.out.println(yesitcontains);
}
}
if (yesitcontains = true){
return true;
}else
return false;
}
}

You have inadvertently used the assignment operator where you intended the equality operator. In your specific case you should rewrite all this:
if (yesitcontains = true){
return true;
}else
return false;
}
to just
return yesitcontains;
and avoid any chance of confusion.
Furthermore, your algorithm will not work because you should return true immediately when you see a duplicate. Instead you go on with the loop and "forget" your finding. You can expect this to always return false except if the very last elements coincide.
In a wider context, I should also give you the following general advice:
Avoid indexed iteration over lists. Not all lists are ArrayLists and may show O(n) complexity for get(i). Instead use the enhanced for loop, which is safer, more concise, and more obvious;
Know the library: if you're just after confirming there are no duplicates, just Collections.disjoint(list1, list2) would give you what you need;
Be aware of algorithmic complexity: checking for duplicates in two lists is O(n2), but if you turn one of them into a HashSet, you'll get O(n).
Taking everything said above into account, the following would be an appropriate implementation:
static boolean disjoint(Collection<?> c1, Collection<?> c2) {
for(Object o : c1)
if (c2.contains(o))
return true;
return false;
}
If you look at Collections.disjoint, you'll find this exact same loop, preceded by a piece of code which optimizes the usage of sets for reasons described above.

Seems to me your method should be rewritten to:
public static boolean contains(List<String>list1, List<String>list2) {
return list2.containsAll(list1);
}
The code you currently have actually only checks if the last element of list1 is also in list2.
If you're actually looking for a contains any, this simple solution will do:
public static boolean contains(List<String>list1, List<String>list2) {
for (String str : list1) {
if (list2.contains(str)) {
return true;
}
}
return false;
}

if (yesitcontains = true){
should be
if (yesitcontains == true){
== is for comparison and = is for assignment.
if (yesitcontains = true){
will always evaluate to if(true) which causing return true;
EDIT:
(OR)
simply return yesitcontains; as commented.

if (yesitcontains == true) { } // use `==` here
or just
if (yesitcontains) { }
The below code assigns true to yesitcontains , and the expression will always be true.
if (yesitcontains = true) { }
There is no point of if() in your code , you can simple return yesitcontains;

Related

Is there a way to merge this 2?

I'm running out of idea of how will I merge this 2 conditions, it has the same return so I need to merge
if ((StringUtils.isBlank(ext))) {
return true;
}
for (String str : INVALID_EXTENSION_ARR) {
if (ext.matches(str)) {
return true;
} else if (ext.matches(str.toLowerCase())) {
return true;
}
}
You don't need a loop.
Populate INVALID_EXTENSION_ARR with values in lowercase:
private static final List<String> INVALID_EXTENSION_ARR = Arrays.asList("foo", "bar", "whatever"); // Note: All in lowercase!
Then it's just one line:
return StringUtils.isBlank(ext) || INVALID_EXTENSION_ARR.contains(ext.toLowerCase());
Note: I have assumed when you used matches() you meant to use equals().
——-
If the list of acceptable extensions is “large” (say, more than 10), you’ll get better performance if you use a Set instead of a List:
private static final Set<String> INVALID_EXTENSION_ARR = new HashSet<>(Arrays.asList("foo", "bar", "whatever"));
Or for recent java versions:
private static final Set<String> INVALID_EXTENSION_ARR = Set.of("foo", "bar", "whatever");
But you would be unlikely to notice much difference unless the size was more than say 100.
Assuming that the loop will always be entered into,
for (String str : INVALID_EXTENSION_ARR) {
if (StringUtils.isBlank(ext) || ext.matches(str)) {
return true;
} else if (ext.matches(str.toLowerCase())) {
return true;
}
}
but I think that way that had it was easier to read and does not need to re-evaluate StringUtils.isBlank(ext) every time.
It is helpful if you provide more context, but this is one of the ways you can compact it.
for (String str : INVALID_EXTENSION_ARR) {
if (StringUtils.isBlank(ext) || ext.toLowerCase().matches(str.toLowerCase())) {
return true;
}
}

LinkedList can not be converted to boolean, what am i doing wronge?

I am currently learning Java. Today I am making a little program where I input numbers and the program shall write if they are sorted or not.
I think I got the logic right, but I got a little error that I can't handle.
package inlamningsuppgift_arSorterad;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class ifSorted {
public static void main(String[] arg) {
LinkedList a = new LinkedList();
Scanner sc = new Scanner(System.in);
System.out.println("Input your numbers, end with the letter \\n");
while (sc.hasNextDouble())
a.add(sc.nextDouble());
if (ifSorted(a))
System.out.println("List is sorted");
else
System.out.println("List is not sorted");
}
private static boolean ifSorted(LinkedList a) {
Collections.sort(a);
return a;
}
}
make this substitution! it work with Java8:
1- a.stream().sorted().collect(Collectors.toList() create a new sorted list
2- .equal(a) the new list comes compares the current
private static boolean ifSorted(LinkedList a) {
return a.stream().sorted().collect(Collectors.toList()).equals(a);
}
Lets take a look at your aerSorterat method.
private static boolean aerSorterat(LinkedList a) {
Collections.sort(a);
return a;
}
private static boolean means that your method will return a boolean which is either true or false .You inserted list [a] then returned [a] .No boolean .With your code You don't need that method.However you must cut the if else statement out of the loop so that after the user inserts a String for ex: out. It checks your list out side the loop.You can use the method if you want by inserting your if else statement in it and returning true or false then calling that method in the main method using ifsorted.aerSorterat(a);
You are actually trying to sort your list there with Collections.sort(a), but if you want to see if your values are sorted, you can do it e.g. with a loop like this:
private static boolean isSorted(List<Double> list) {
return ascending(list) || descending(list);
}
If you have to check both ways, you easy do that with both methods connecting with an ||, which is an logical or.
The single methods simply check if all values in a list are greater (ascending) oder lesser (descending) then their predecessors.
private static boolean ascending(List<Double> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i - 1) > list.get(i))
return false;
return true;
}
private static boolean descending(List<Double> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i - 1) < list.get(i))
return false;
return true;
}
If one of the values doesn't fit the premise, it simply returns false. If the loop is completed and left normally, that means that all values are sorted.
But to do that, you have to give the generic parameter <Double> as a parameter to your method, otherwise you cannot compare the values with < and >. Also I use List instead of LinkedList because with that given, you can use any kind of List you want.
If you want to use other objects than numbers, you need to change it a little.
First possability is, the objects you want to use have to implement the Comparable Interface, which provides the compareTo(...) method. Which that given, you can is it e.g. like the following:
public boolean ascending(List<YourObject> list) {
for (int i = 1; i < list.size(); i++)
if (list.get(i-1).compareTo(list.get(i)) > 0)
return false;
return true;
}
Simply swap the operator for descending. This e.g. can be used with a list of Strings.

Checking an array list against another array list

This is a method in a spell checker. As the header explains, it should return true if and only if all the words added to the arraylist are found in the parent array, words. Otherwise it should return a false value. I've been fighting with this for a few hours and this is my current situation...
/**
* This method returns true if (and only if) all words in the
* given wordList are found in the dictionary.
*/
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(int index = 0; index < wordList.size(); index++)
{
if(words.contains(!wordList.contains(index)))
{
result = false;
}
result = true;
}
return result;
}
All I really need is a way to turn out a yes or no, but I'm lost.
Please try and work with the code given as this is an exercise to teach that code.
Thanks!
Your problem is here:
if(words.contains(!wordList.contains(index)))
!wordList.contains(index) is a boolean expression, so it always evaluates to either true or false. So you're actually checking if the words list contains true or false, not the word like you want. Replace it with if(!words.contains(wordList.get(index)) to check if the current word is found in the dictionary.
I would suggest a following solution: iterate wordList word by word, and for each word check if it's found in the dictionary. If not so, return false immediately. If you reach the end of the loop, return true.
Here could be another solution:
public static boolean allKnown(List<String> parent, List<String> child) {
List<String> temp = new ArrayList<String>(child);
temp.removeAll(parent);
return temp.isEmpty();
}
For example:
List<String> parent = Arrays.asList("w1", "w2", "w3", "w4");
List<String> childOk = Arrays.asList("w1", "w4");
List<String> childKo = Arrays.asList("w1", "xx");
System.out.println(allKnown(parent, childOk));
System.out.println(allKnown(parent, childKo));
Prints:
true
false
Take out result = true; - you don't want to reset the value to true at every step in the loop.
Also change wordList.contains to wordList.get (because you want to get the word at a specific index, not check if it's contained in wordList) and move the ! out (because you can't 'not' a string).
And you can also optimize by checking result's value in the for-loop condition (or simply returning directly in the if-statement).
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(int index = 0; index < wordList.size() && result; index++)
{
if(!words.contains(wordList.get(index)))
{
result = false;
}
}
return result;
}
If words really is an array and not an ArrayList, it doesn't have a contains method, you'll have to either have a double for-loop, or convert it to a list:
List<String> parentWords = Arrays.asList(words);
...
if (parentWords.contains(...))
Don't reset result to true after your if. Because like this the whole function will always return true.
A few tips:
Don't use ArrayList as a method parameter, always use the more abstract List (none of your code depends on ArrayList, so you can change the implementation later, if you like).
Iterate over List objects using the simplified syntax shown below.
You only need one word to be not in the words list to return false, so do exactly that (as shown below).
public boolean allKnown(List<String> wordList) {
for (String word : wordList) {
if (!words.contains(word)) {
return false;
}
}
return true;
}
public boolean allKnown(ArrayList<String> wordList)
{
boolean result = true;
for(String word : wordList)
{
if(!words.contains(word))
{
result = false;
}
}
return result;
}
Here is a simpler version :
public boolean allKnown(List<String> wordList) {
List<String> wordListCopy = new ArrayList<String>(wordList);
return !wordListCopy.retainAll(words);
}
PS : retainAll() removes from you wordList all of its elements that are not contained in you dictionnary. This method return true if your wordList changed as a result of the call (after removing the non existing element), in other word, this method return false when all your wordList elements exists in you dictionnary.

Comparing one ArrayList to another ArrayList using boolean method in java

I am trying to get a boolean method to return true or false on wether two arrayLists are equal to each other. The arraysLists are array and array1. The user inputs them. Right now here is the code that I thought would work:
public boolean equals(){
//if both are equal return true, else false
boolean test = false;
for(int i = 0; i < array1.size() && !test; i++){
if(array1.get(i) == (array.get(i))){
test = true;
}
}
return test;
}
except even when all the arrayLists numbers match the other arrayLists numbers, it returns false.
You don't need to overwrite the equals method, as there is one already provided for lists that does exactly what you need.
If you insist of writing it yourself there is a simple error in your code.
Because you initialize test to be false, "&& !test" lets your loop exist right at the start.
The correct version would be:
public boolean equals(){
if(array.size()!=array1.size) return false; // test for different length
for(int i = 0; i < array1.size(); i++){
if(!array1.get(i).equals(array.get(i))){
return false;
}
}
return true;
}
double equals (==) is dangerous. You are actually returning objects in your code up there, so you should definitely use equals() instead
Think that you are only iterating one array. Think what can go wrong there. Also take a look at your control statement.
If you carefully follow the flux of your code you quickly will realize why is false.
You should just 'reverse' your method. Assume the arrays are equal first. It should then check on each iteration if the element differs. If the element differs, then set a "not equal" flag. In pseudo-codee
boolean different = false;
for (each element of array 1) {
if (element != element of array 2) different = true
break;
}
You'll need to change your code to this:
public boolean equals(){
if (array1.size() != array.size()) return false;
for(int i = 0; i < array1.size(); i++){
if(!array1.get(i).equals(array.get(i))){
return false;
}
}
return true;
}
First off, you have to start with test being true and return false if you find something that isn't equal, because this clearly shows that the ArrayLists are not equal. You actually don't need the test variable at all, so I took it out. Just return false if you find something that isn't equal. If you don't find something that isn't equal, it will never return false and will just return true at the end. Second, you have to use the equals() method, because ArrayLists use the Integer class, not the int primitive so == will check if they are the same object, not if they are the same number. Lastly, to deal with comparing arrays of different sizes, you should compare their size and return false if they are not the same size, since there is no way they can be equal.

Search an attribute inside a Vector on Java

I've a Vector of objects, and have to search inside for a random attribute of those objects (For example, a Plane class, a Vector containing Plane; and I've to search sometimes for destination, and others to pilotName).
I know I can traverse the Vector using an Iterator, but I've got stuck at how do I change the comparison made between a String and the attribute on the object. I thought of using switch, but a another opinion would be cool.
Update 1:
The code I've written is something like this (Java n00b alert!):
public int search(String whatSearch, String query){
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
/* Here is where I have to search for one of many attributes (delimited by whatSearch */
}
return place;
}
Seems I've to stick to linear search (and that's a price I've able to pay). Anyway, I was thinking if Java had something like variable variable name (ouch!)
I assume that your problem is that you want to have a method that searches for a result based on some property of the collection type. Java is weak on this because it is best expressed in a language which has closures. What you need is something like:
public interface Predicate<T> {
public boolean evaluate(T t);
}
And then your search method looks like:
public static <T> T findFirst(List<T> l, Predicate<T> p) { //use List, not Vector
for (T t : l) { if (p.evaluate(t)) return t; }
return null;
}
Then anyone can use this general-purpose search method. For example, to search for an number in a vector of Integers:
List<Integer> is = ...
findFirst(is, new Predicate<Integer> {
public boolean evaluate(Integer i) { return i % 2 == 0; }
});
But you could implement the predicate in any way you want; for any arbitrary search
Use Collections.binarySearch and provide a Comparator.
EDIT: This assumes that the Vector is sorted. Otherwise, one has to do a linear search.
the equals() method is the best option. For these iterations you could do something like this:
for (Plane plane: planes) {
if ("JFK".equals(plane.getDestination())) {
// do your work in here;
}
}
or you could override the equals() method within Plane to see if the String passed in matches your destination (or pilot). this will allow you to use the indexOf(Object) and indexOf(Object, index) methods on Vector to return you the index(es) of the object(s). Once you have that, you could use Vector.get(index) to return to Object for you.
in Plane.java:
public boolean equals(Object o) {
return o.equals(getDestination()) ||
o.equals(getPilot()) ||
super.equals(o);
}
there is more work to be done with this option, as you will need to override hashCode() as well (see documentation).
See #oxbow_lakes above -- I think what you want isn't to pass a String as whatSearch, it's to pass a little snippet of code that knows how to get the property you're interested in. For a less general version:
public static interface PlaneMatcher {
boolean matches(Plane plane, String query);
}
public int search(PlaneMatcher matcher, String query){
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
if (matcher.matches(temp, query) {
found = true;
}
place++;
}
return place;
}
...
// example
int pilotNameIndex = search(new PlaneMatcher() {
boolean matches(Plane plane, String query) {
// note: assumes query non-null; you probably want to check that earlier
return query.equals(plane.getPilotName());
}
}, "Orville Wright");
(By the way, if it's the index you're interested in rather than the Plane itself, I wouldn't bother with an Iterator -- just use an old-fashioned for (int i = 0; i < planes.size(); i++) loop, and when you have a match, return i.)
Now, the tricky bit here is if what you have to search for is really identified by arbitrary strings at run-time. If that's the case, I can suggest two alternatives:
Don't store these values as object fields -- plane.pilotName, plane.destination -- at all. Just have a Map<String, String> (or better yet, a Map<Field, String> where Field is an Enum of all the valid fields) called something like plane.metadata.
Store them as object fields, but prepopulate a map from the field names to PlaneMatcher instances as described above.
For instance:
private static final Map<String, PlaneMatcher> MATCHERS = Collections.unmodifiableMap(new HashMap<String, PlaneMatcher>() {{
put("pilotName", new PlaneMatcher() {
boolean matches(Plane plane, String query) {
return query.equals(plane.getPilotName());
});
...
put("destination", new PlaneMatcher() {
boolean matches(Plane plane, String query) {
return query.equals(plane.getDestination());
});
}}
...
public int search(String whatSearch, String query){
PlaneMatcher matcher = MATCHERS.get(whatSearch);
int place = -1;
boolean found = false;
for ( Iterator<Plane> iteraPlane = this.planes.iterator(); iteraPlane.hasNext() && found == false; ) {
Plane temp = (Plane) iteraPlane.next();
if (matcher.matches(temp, query) {
found = true;
}
place++;
}
return place;
}
Oh, and you might be tempted to use reflection. Don't. :)
A simple way is to pass a comparison function to your search routine. Or, if you need more speed, use generics.

Categories