The way you have coded the comparation repeats itself. Besides, that is not the correct way you access an element in a list, I'm afraid.
For example, lets say you have the i = 0 (value 2.0 for example) and k = 2 (value 5.2), but later you have i = 2 (5.2) and k = 0 (2.0), which is the same. I suggest you the following, which avoids this repetition.
for (int i = 0; i < list.size()-1; i++)
for (int k = i+1; k < list.size(); k++)
if(list.get(i) == list.get(k))
System.out.println(i + " and "+ k +" are pairs");
Of course, you have to make sure that the list's size is bigger than 1, otherwise it will throw OutOfBoundsException. Hope this helps ^^
EDIT #2 Try and use the following if, it contains a null-safe equals:
if(Objects.equals(list.get(i), list.get(k)))
Answer from fasaas on Stack OverflowThe way you have coded the comparation repeats itself. Besides, that is not the correct way you access an element in a list, I'm afraid.
For example, lets say you have the i = 0 (value 2.0 for example) and k = 2 (value 5.2), but later you have i = 2 (5.2) and k = 0 (2.0), which is the same. I suggest you the following, which avoids this repetition.
for (int i = 0; i < list.size()-1; i++)
for (int k = i+1; k < list.size(); k++)
if(list.get(i) == list.get(k))
System.out.println(i + " and "+ k +" are pairs");
Of course, you have to make sure that the list's size is bigger than 1, otherwise it will throw OutOfBoundsException. Hope this helps ^^
EDIT #2 Try and use the following if, it contains a null-safe equals:
if(Objects.equals(list.get(i), list.get(k)))
First, you should fix:
if(list[i]= list[k]){
To be:
if(list.get(i) == list.get(k)){
Second, you should add a condition to make sure i != k (or in other words - you're not comparing an element to itself.
And third, you can't access a list like you do: list[i] you should use list.get(i)
java - Comparing list elements in an effective way - Code Review Stack Exchange
Java Compare Two Lists - Stack Overflow
A question about the comparison of elements in two ArrayLists in java.
java - Comparing each element of a list to all other elements of the same list - Code Review Stack Exchange
Instead of implementing
isSameimplementequalsandhashCode. After that you could use aHashSet(orLinkedHashSetif the order of elements is important). Set is a collection that contains no duplicate elements and inserting/searching is much faster than searching in a list.Set<GameState> opened = new LinkedHashSet<GameState>(); public void addEverything() { List<GameState> list = current.neighbours; for (GameState state : list) { opened.add(state); } }If you need a list, you can convert it back after the loop:
List<GameState> openedList = new ArrayList<GameState>(opened);See also: Overriding equals and hashCode in Java
According to the Java Code Conventions, class names in Java usually starts with uppercase letters.
palacsint's answer is good, but it's missing just a few things.
All in-built Java collection classes I can think of has copy-constructors, and an addAll method. So your addEverything method can be a one liner, when using a Set<GameState>:
public void addEverything() {
opened.addAll(current.neighbours);
}
Or, if you would like to reset the contents and create an entirely new Set, use the copy-constructor:
public void replaceEverything() {
opened = new LinkedHashSet<GameState>(current.neighbours);
}
Since it can become a one-liner, you might not need to have it in it's own method.
Most importantly, if you are not interested in the order of the opened set, use a HashSet rather than a LinkedHashSet.
EDIT
Here are two versions. One using ArrayList and other using HashSet
Compare them and create your own version from this, until you get what you need.
This should be enough to cover the:
P.S: It is not a school assignment :) So if you just guide me it will be enough
part of your question.
continuing with the original answer:
You may use a java.util.Collection and/or java.util.ArrayList for that.
The retainAll method does the following:
Retains only the elements in this collection that are contained in the specified collection
see this sample:
import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
public class Repeated {
public static void main( String [] args ) {
Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));
listOne.retainAll( listTwo );
System.out.println( listOne );
}
}
EDIT
For the second part ( similar values ) you may use the removeAll method:
Removes all of this collection's elements that are also contained in the specified collection.
This second version gives you also the similar values and handles repeated ( by discarding them).
This time the Collection could be a Set instead of a List ( the difference is, the Set doesn't allow repeated values )
import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;
class Repeated {
public static void main( String [] args ) {
Collection<String> listOne = Arrays.asList("milan","iga",
"dingo","iga",
"elpha","iga",
"hafil","iga",
"meat","iga",
"neeta.peeta","iga");
Collection<String> listTwo = Arrays.asList("hafil",
"iga",
"binga",
"mike",
"dingo","dingo","dingo");
Collection<String> similar = new HashSet<String>( listOne );
Collection<String> different = new HashSet<String>();
different.addAll( listOne );
different.addAll( listTwo );
similar.retainAll( listTwo );
different.removeAll( similar );
System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
}
}
Output:
$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]
Two:[hafil, iga, binga, mike, dingo, dingo, dingo]
Similar:[dingo, iga, hafil]
Different:[mike, binga, milan, meat, elpha, neeta.peeta]
If it doesn't do exactly what you need, it gives you a good start so you can handle from here.
Question for the reader: How would you include all the repeated values?
You can try intersection() and subtract() methods from CollectionUtils.
intersection() method gives you a collection containing common elements and the subtract() method gives you all the uncommon ones.
They should also take care of similar elements
I'm trying to do my homework
I created two ArraLists of Integer, and the content in the list is as follows:
List1:
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 150
List2:
150 300 450 600 750
when i use
list1. get(list1. size() - 1) == list2. get(0);
I get false;
I have to use
list1.get(list1.size() - 1).equals(list2.get(0));
to get true;
Then I try the following code:
ArrayList<Integer> arrList1 = new ArrayList<Integer>();
ArrayList<Integer> arrList2 = new ArrayList<Integer>();
arrList1. add(10);
arrList2.add(10);
System.out.println(arrList1.get(0) == arrList2.get(0));
I get true;
I know that == can only be used to compare values, or Primitive types, while .equals() is used to compare references.
I'm sure what I'm storing in the ArrayList is integer, int, so why can't I use == for comparison? (And I'm also wondering why comparing 10 with == gets true and 150 gets false)
I wonder why this is happening?
Thanks in advance to everyone who helped me.
getDatais no better thandoStuff()as the name of a function.getDataNotVarandgetDataAndVarare only slightly better, and are useless to me, as i don't know whatDataorVaryou'regetting. :PfirstListIsCompletelyContainedInMainListis reinventing the wheel. Collections have acontainsAllmethod. Use that.public static boolean firstListIsCompletelyContainedInMainList(List<String> list1, List<String> list2) { if (isStringListNullOrEmpty(list1)) return true; if (isStringListNullOrEmpty(list1)) return false; return list2.containsAll(list1); }But we can do better.
You're using a suboptimal type for the type of operation you're doing here. If you stuff the items into a
HashSet<String>, and check against that, your check goes from O(NM) to O(N+M).public static boolean firstListIsCompletelyContainedInMainList(List<String> list1, List<String> list2) { if (isStringListNullOrEmpty(list1)) return true; if (isStringListNullOrEmpty(list1)) return false; Set<String> mainContents = new HashSet<>(list2); return mainContents.containsAll(list1); }Ideally, you'd be using
Set<String>rather thanList<String>anyway, if this is the main operation you're performing on these "lists". I can't say whether that's a good idea in your particular case, though, as you haven't shown anything else you're doing.When you're returning the results of conditional tests, do it directly. Don't say
if (x) return true; else return false;. Justreturn x;.public static boolean isStringListNullOrEmpty(List<String> stringList) { return (stringList == null || stringList.isEmpty()); }Ideally, though, you'd make it so
getDataAndVar()andgetDataNotVar()always return an empty collection rather thannull. (It feels a bit hinky when you don't know whether you have an object or not.) Once you do that, this function can go away entirely...as can the null checks infirstListIsCompletelyContainedInMainList. (You might keep an.isEmpty()check if you're trying to optimize, but any savings might not be worth the extra code. If you care, measure it.)By the way, your names are extremely wordy. Maybe that's just a Java thing. :P But
firstListIsCompletelyContainedInMainListcould be replaced by, say,listContainsListif you swaplist1andlist2around.
First of all, let me point out that removing elements from a list that you're iterating over is pretty dangerous in general.
The outer loop itself isn't a problem, since you're going over the indices starting at the end and going to the start. Removing the item at the current index doesn't have any effect on the indices that will be handled in the next iterations.
However, when we nest 2 for loops iterating over all the elements we would run into problems.
Let's say you have the list {A,B,C,D}. We ignore comparing D to D. Next we compare D to C and conclude that C can be removed. Next we compare D to B and conclude B can be removed. Finally compare D to A and do nothing. Now the next x will be 2. But since we removed B and C from our list the function list.get(2) will throw an IndexOutOfBoundsException.
It seems you tried to solve this problem by using a break statement to jump out of the inner for loop whenever you remove an item. But this has introduced a new mistake.
Let's say in the same list you are comparing C to D and conclude that D can be removed. You now break out of the inner loop and continue with B. But by doing so you skipped comparing C to B and comparing C to A.
So then what can we do to solve this correctly? Instead of directly removing the VG's from the list we should just mark the VG's for removal in the first pass.
Then after the outer for loop has ended, we loop over all the marked VG's again and safely remove them from the list.
We can also simplify the loops a little bit if we check the contains both ways at once. The code will look like this:
List<TreeDataGroup> markedForRemoval = new ArrayList<>();
for (int x = treeDataGroups.size()-1; x >= 0; x--) {
TreeDataGroup treeDg1 = treeDataGroups.get(x);
//**important** notice the y>x instead of y>=0
for (int y = treeDataGroups.size()-1; y > x; y--) {
TreeDataGroup treeDg2 = treeDataGroups.get(y);
if (treeDg1 fully contains treeDg2) {
markedForRemoval.add(treeDg2);
}
if (treeDg2 fully contains treeDg1) {
markedForRemoval.add(treeDg1);
}
}
}
for(TreeDataGroup group : markedForRemoval){
treeDataGroups.remove(group);
}
If I understood your initial explanation correctly the lists inside the datagroups are sorted. So I think we can do both checks at the same time with something like this: (disclaimer: I did not test this code, you might have to correct it to get it to work). Note that I'm also assuming the lists are non-null but default to an empty list like @cHao suggested in his answer.
private void markGroupForRemoval(TreeDataGroup group1, TreeDataGroup group2, List<TreeDataGroup> markedGroups){
boolean markg1 = true;
boolean markg2 = true;
int i1 = 0;
int i2 = 0;
while(i1 < group1.getDataAndVar().length
&& i2 < group2.getDataAndVar().length
&& (markg1 || markg2)){
if(group1.getDataAndVar().get(i1) == group2.getDataAndVar().get(i2)){
i1++;
i2++;
} else if(group1.getDataAndVar().get(i1) < group2.getDataAndVar().get(i2)){ //note, you should change this to a string comparison I believe
//group 1 contains an element that group2 does not.
markg1 = false;
i1 ++;
} else {
//group 2 contains an element that group1 does not.
markg2 = false;
i2 ++;
}
}
//do the same thing for getDataNotVar, but mark the oposite.
i1 = 0;
i2 = 0;
while(i1 < group1.getDataNotVar().length
&& i2 < group2.getDataNotVar getDataNotVar().length
&& (markg1 || markg2)){
if(group1.getDataNotVar().get(i1) == group2.getDataNotVar().get(i2)){
i1++;
i2++;
} else if(group1.getDataNotVar().get(i1) < group2.getDataNotVar().get(i2)){ //note, you should change this to a string comparison I believe
//group 1 contains a not-element that group2 does not.
markg2 = false;
i1 ++;
} else {
//group 1 contains a not-element that group2 does not.
markg1 = false;
i2 ++;
}
}
if(markg1){
markedGroups.add(group1);
}
if(markg2){
markedGroups.add(group2);
}
}
Notice here that as soon as we marked both groups as still needed (so both markg1 and markg2 are false) then we quit the while loop early.
If you can get this to work it should speed things up a bit (or a lot, if the early exit while checking happens fast consistently).
You'll need to at least replace the < with the correct comparison check. (StringComparitor?). Maybe group2.getDataAndVar().length should be group2.getDataAndVar().size() instead. And check the logic because I might have switched the cases around by accident.
If you're familiar with merge sort this algorithm should be relatively easy to understand.
EDIT: as per suggestion by @cHao, we're now comparing VG's even if they're already marked for removal. Since the checks themselves are rather expensive it's better to avoid that.
My first solution for this would be something like this:
List<TreeDataGroup> markedForRemoval = new ArrayList<>();
for (int x = treeDataGroups.size()-1; x >= 0; x--) {
TreeDataGroup treeDg1 = treeDataGroups.get(x);
for (int y = treeDataGroups.size()-1; y > x; y--) {
TreeDataGroup treeDg2 = treeDataGroups.get(y);
if(marmarkedForRemoval.contains(treeDG2) {
continue;
}
markGroupForRemoval(treeDG1, treeDG2, markedForRemoval);
if(markedForRemoval.contains(treeDG1){
break;
}
}
}
Where the check for treeDG2 results in skipping that one in the inner loop only (if we would break out of the loop we get the same missing checks like before). And the check for treeDG1 right after the marking means that since the VG of the outer loop is marked, there's no reason to continue checking that one against the rest of the inner loop.
But we can actually do a little better than this. Remember that I said that removing in a single for loop is safe? Let's use that fact and place the removal inside the outer for loop:
List<TreeDataGroup> markedForRemoval = new ArrayList<>();
for (int x = treeDataGroups.size()-1; x >= 0; x--) {
TreeDataGroup treeDg1 = treeDataGroups.get(x);
for (int y = treeDataGroups.size()-1; y > x; y--) {
TreeDataGroup treeDg2 = treeDataGroups.get(y);
markGroupForRemoval(treeDG1, treeDG2, markedForRemoval);
if(markedForRemoval.contains(treeDG1){
break;
}
}
for(TreeDataGroup tdg : markedForRemoval){
treeDataGroups.remove(tdg);
}
markedForRemoval.clear();
}
Now we're sure that we check all combinations but without doing any unnecessary checks.
I did however spot a mistake thanks to @cHao's comment. If the 2 VG's are exactly the same, both will be marked for removal. This is not what we want. So let's fix this at the end of the markGroupForRemoval method
if(markg1){
markedGroups.add(group1);
return; //important. If both are equal, we shouldn't remove them both.
}
if(markg2){
markedGroups.add(group2);
}
}
Can I sort two arraylists containing objects so that I can compare them and their contents? I tried to type in:
Collections.sort.myArrayList but it wouldnt work!