I have a custom object in this structure
static class Node {
int col;
int row;
int g;
int h;
int f;
public Node(int col, int row, int g, int h) {
this.col = col;
this.row = row;
this.g = g;
this.h = h;
this.f = g+h;
}
}
The col
and row
variables are unique, and may only occur once in ArrayList<Node> myList
.
Is there a way optimal way to avoid adding or checking for possible duplicate without having to make a nasty for-loop?
I am aware that Set
interface possibly could be a solution for this as duplicates cannot occur, but i have alot of code right now, which i do not want to refactor unless it becomes necessary.
Ideally, you'd use
Set
, but if you'd like to avoid reimplementing your data structures fromArrayList<Node>
toSet
, you can implementSet
as a gatekeeper:And thus it's a "gatekeeper".
All of the Set operations are
O(1)
since they are hashed; minimal refactoring and no nasty loops as desired.Keep both a Set and a List. Use the Set to check for duplicates. Add to both Set and List if no dupe.
...assuming that Node has an .equals method defined...
I always find weird to see cases where people want to use a
List
(for theget(int)
method, I guess) when they require unicity, which is only achieved throughSet
.Anyway, by manipulating a little the equals/hashcode (making equals return
true
whenrow
andcol
are the same) method and adding calls toList#contains(Object)
, you could have your goal reached without sacrifying yourList
EDIT
Notice you could also create a Comparator and rely upon
Collections#sort(List, Comparator)
to have your list sorted and items with the same value melted into only one value.Add a equals method in Node if possible :
And then use
list-to-set-to-list
trick.Try this method:
Update :
If you wan't to maintain input order, use
LinkedHashSet
Here are your options. All of these solutions require proper implementation of
equals
andhashCode
. Since you wantrow
andcol
to be unique:Iterate over the
List
You don't have to do the iteration yourself, but that is exactly what calling
List.contains
will do. This one is pretty easy:This will iterate for you, so you don't have to write the loop.
List
toSet
toList
Here you have two sub-options. If you want to preserve the order of your input list, then you can use
LinkedHashSet
. If you don't care, you can just useHashSet
. What I mean is if I have aList
with elements A, B, C, converting it to aHashSet
and back may produce a different list, like B, C, A.LinkedHashSet
keeps the elements in insertion order, avoiding this problem. In any case, you'll just do this:Remember that this is essentially doing iteration as well, but it's using a hash-code shortcut instead of checking every element's equality, which may be a big deal with enough nodes. If your node list is small (less than 1000 elements) then I doubt this will make much of a difference, and you may as well use the first one.
Converting everything to
Set
You mentioned that this would require a lot of refactoring in your code, but this isn't a bad thing, especially if you plan on working on this code a lot in the future. My rule of thumb is if the refactoring will make the code easier to maintain, adding a little extra development time is never a bad thing. Writing maintainable, readable, and understandable code is what the experts do (the question here isn't relevant, but this particular answer is). Since
Set
implies unique elements andList
does not, then it makes sense to make the change. The compiler will pretty much tell you all the places you have to change with its errors, and it might take less time than you think.Add all the elements to a new
Set
, then put all the elements from theSet
to a newList
. That will make it.