What is the best way to store one single additional attribute at an arraylist?
Let's say I pass an ArrayList of Objects to a method and get an ArrayList back with an additional flag.
ArrayList<MyObject> list = new ArrayList<MyObject>();
//fill
list = myMethod(list);
And I want to get a boolean for each Object, but I don't want to store it directly in the object.
So data before myMethod: Apple, Banana, Grapefruit
After myMethod: Apple=>true, Banana=>false, Grapefruit=>false.
How can I store that additional attribute when not in the object? What is the best datatype? ArrayList can not do that, right?
You can create a custom wrapper around Object that has a field of type object and a boolean field. This is the best solution as you will be able to choose a meaningful name for the field.
Alternatively you can use the built-in class Pair and create a List<Pair<MyObject, Bool>>.
Use a class with a List<MyObject> field and a List<Boolean> field whose elements are flags parallel to every MyObject added in your List<MyObject>. Since this is too cumbersome, just add the boolean flag in MyObject. If you can't modify the class, extend it and add the boolean flag in your ExtendedMyObject extends MyObject class. If you can't extend it, make a wrapper class of MyObject that has a MyObject field and the boolean flag.
You could separately maintain a Set<MyObject> - membership in the Set would correspond to a true value for that object.
Assuming you used a HashSet, you would need to ensure MyObject implemented equals and hashCode. An alternative would be uniquely identifying each MyObject with a String, Long, etc. and maintaining a Set of those IDs.
I'd recommend just returning a Map with the source object (or name if unique) mapped to the boolean value.
Map<MyObject,Boolean> result = myMethod(list);
or, if name is unique:
Map<String,Boolean> result = myMethod(list);
for (MyObject item : list) {
Boolean result = result.get(item.getName());
if (result) {
...
}
}
If:
MyObject doesn't implement #hashCode (so you may get missed hashes for equal objects)
name isn't unique or
if result were more complex than a Boolean,
then I'd create a wrapper that wraps a MyObject with a result and return a List<MyObjectResult>.
Edit: BTW, I think you're right not to include the Boolean field on MyObject if it is not really a part of that object's state - i.e. if it's a transient result of some operation.
you can extend the ArrayList and give them a new property. For example:
public class MyArrayList<E> extends ArrayList<E>{
private boolean value;
public boolean isValue() {
return value;
}
public void setValue(boolean value) {
this.value = value;
}
}
there you can have all the features from the ArrayList and you have an additinal boolean field.
EDIT:
If your Boolean value has nothing to do with the Originalobject, why not just write a Wrapperclass? There are 2 possibilities to resolve this:
extend your Baseclass MyObject
Write a new class with 2 properties, one for the boolean and the other your instance of MyObject
Related
I have to make an ArrayList that contains an object, the object has one int for year lets say 1
and I don't what another object with the same year 1.
If one object has the int = 1 , i dont want another object with that int(1) in my list.
i want to deny it.
Should I try using equal?
something like
#Override
public boolean equals(Object o){
Object object = (Object)o;
return this.getInt.equals(object.getInt());
}
Either use a Set...which explicitly disallows duplicates, or check if the list contains the element on insertion.
#Override
public boolean add(T element) {
if(contains(element)) {
return false;
} else {
return super.add(element);
}
}
Overriding equals wouldn't get you very far, as you'd be overriding it for the List itself (i.e. you'd be checking if two lists were equal).
Perhaps you can try using a HashMap linked that links that "int" with the object. That could be:
Map<Integer, Object> map = new HashMap<>();
map.put(object.getInt(), object);
...
//Each time you put a new object you could try this:
if(!map.contains(object.getInt()))
map.put(object.getInt, object);
//And you can retrieve your object by an int
int a = 1;
Object obj = map.get(1);
In this case, as the value is of type int, you can use equal operator.
public boolean equals(Object o){
Object object = (Object)o;
return (this.getInt()==object.getInt());
}
For this kind of requirement, ArrayList is not suggestible. As mentioned in the other answers try using HashMap.
Yes, you can. When you call
myArrayList.contains(myObejct);
the ArrayList will invode myObejct's equals method. So you can tell if the object is already in you list.
And I think you can change you method a little,
#Override
public boolean equals(Object o){
if (!(o instanceof YourClass))
return false;
YourClass object = (YourClass)o;
return this.getInt.equals(object.getInt());
}
because if you don't, the method "getInt" might cause a MethodNotFound exception.
Well, that is one way to approach the problem.
Your equals will probably work provided that you change Object object = (Object)o; to cast to the real class.
However, equals ought to cope with the case where o is not of the expected type. The contract requires you should return false rather than throwing a ClassCastException ...
You would then use list.contains(o) to test if an object with the same int value exists in the list. For example:
if (!list.contains(o)) {
list.add(o);
}
But when you override equals, it is best practice to also override hashcode ... so that your class continues to satisfy the equals / hashcode invariants. (If you neglect to do that, hash-based data structures will break for your class.)
However, this won't scale well, because the contains operation on an ArrayList has to test each element in the list, one at a time. As the list gets longer, the contains call takes longer ... in direct proportion; i.e. O(N) ... using Big O complexity notation.
So it may be better to use a Set implementation of some kind instead on ArrayList. Fepending on which set implementation you choose, you will get complexity of O(1) or O(logN). But the catch is that you will either have to to implement hashcode (for a HashSet or LinkedHashSet), or implement either Comparable or a Comparator (for a TreeSet).
I think that a final reference to an array of enums should be immutable.
The uniqueness and singularity of enums is enforced by the JVM, so I believe it is safe to say that they are immutable.
A final reference cannot be changed, so the reference is immutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
I have a list of enums that correspond to database columns. These column names and their associated data do not change, so ... I would like to have the list as a class variable like so:
static final List<MetaData<Client>> C_COLUMNS =
DataTables.CLIENTS.getTableColumnsAsEnums();
where CLIENTS is the DataTable enum for which a list of column enums is being generated. The method that does this follows:
public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() {
Class<? extends MetaData> cls = this.columnsEnumToken();
return new ArrayList(Arrays.<MetaData<T>>asList(cls.getEnumConstants())); }
Am I right? This ought to become part of a multi-threaded design, and so I am concerned about the way that making this critical list of static data would render by app very vulnerable ... if it actually were mutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
Yes. All arrays in Java are mutable, irrespective of how you declare the variable that holds the reference to the array.
If you want to avoid this "risk", then you must not expose the array; i.e. you need to declare it as private. You could then do one (or more) of the following:
Define a static method that will create and return a copy of the array. (Probably not the best option here ...)
Define a static get(int) method that returns the ith element of the array.
Wrap the array in a list (using Arrays.asList) and create an unmodifiable wrapper for it (using Collections.unmodifiableList).
If you want to get the public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() to return an immutable List you need to use Collections.unmodifiableList()
Also when you are using an unmodifiable list you don't have to worry about the internal array because the toArray method will return an copy of the internal array, not a reference to the internal array itself. This is true for all the Collections.
The REFERENCE is immutable, the content of that reference is not, that's just how things work.
So the following won't work
public enum TheEnum {
//......
}
final TheEnum[] arr = new TheEnum[5];
var = new TheEnum[6];
but this will work
public enum TheEnum {
OPTION_ONE;
//......
}
final TheEnum[] arr = new TheEnum[5];
var[1] = TheEnum.OPTION_ONE;
I have a question regarding I guess the scope of objects and whether or not the values the object holds would be changed under certain conditions.
For example, I have made a class in which I need to contruct more than 1 instance of the object, but these instances need to be used and modified throughout the programm and no new instances should be made after the first are made (I don't know what design pattern this would be following if any). The way I have designed the object is something similar to the following:
//basic constructor class
public class MyObject {
private String var1;
private int var2;
private boolean vr3
public MyObject(String param1, int param2, boolean param3) {
var1 = param1;
var2 = param2;
var3 = param3;
}
//getter and setter methods
}
//in main class
Map<String, MyObject> myObjects = new HashMap<String, MyObject>();
on the start of my program, I search through some files to construct new MyObject objects then put them in the HashMap and that is the only time a new MyObject should be created. So throughout the program, I get the objects in the HashMap by getting the value that matches the String key, and once I have that object, I may do things to it using the different setter methods like below:
MyObject object1 = MyObjects.get("anObject");
object1.setVar1("This is the objects new var1 string value");
And that code above should change the string value in the object that is in the HashMap under the key "anObject". But I am wondering that should this also work for things like Lists? like say I had a list as one of the values in the object, and if I got that object from the HashMap, and called something like:
object1.getList().add("new value in the object1 list");
would that add the value to the object in the hashMap? I am wondering this because since I called:
MyObject object1 = MyObjects.get("anObject");
it seems like it could be creating a new instance of that class or just copying it over and that any changes to that object1 object wont be made to the object in the HashMap.
Am I correct that the changes made to any values to the object gotten form the HashMap will be put back to the object in the HashMap?
Sorry for this stupid question.
Java is pass by value, however MyObject is a reference and this is passed by value.
This means every copy of a reference to your Object is the same object and wherever you attempt to change it, the same object will be changed.
The object itself will only be copied when you copy it, not implicitly.
You are correct: any changes made to the internals of the object that you retrieve from the HashMap will be changed in the HashMap, as when you retrieve an object from any data structure, you are actually getting a pointer to an object, so the HashMap and the pointer you get back both point to the same object data. The only times when this is different is if you are storing primitives (like int, double, float, etc.) or if you reconstruct the object you have received from the HashMap.
I have a list of MyObjects which I need to divide into three groups:
Known good (keep)
Known bad (reject)
Unrecognized (raise alert)
MyObject contains various properties which must be examined to determine which of the 3 groups to put the object in.
My initial implementation (Java) just takes a List in its constructor and does the triage there. Pseudocode:
class MyObjectFilterer {
public MyObjectFilterer(List<MyObject> list) {
// triage items here
}
public List<MyObject> getGood() {
// return sub-list of good items
}
public List<MyObject> getBad() {
// return sub-list of bad items
}
public List<MyObject> getUnrecognized() {
// return sub-list of unrecognized items
}
}
Any issues with this implementation? Is there a better OO choice?
I would probably prefer a static factory method to do the filtering, that then calls a private constructor that takes the three filtered lists, following the good code practice of never doing any serious work in a constructor. Other than that, this looks fine.
There may be multiple approachs. If the problem is generic / repetitive enough, you could define an interface with a method to classify the objects.
interface Selector {
public boolean isGood(MyObject myObject);
public boolean isBad(MyObject myObject);
public boolean isUnknown(MyObject myObject);
}
That way you could change the logic implementation easily.
An other idea would be using the Chain of responsibility.
Your MyObjectFilterer contains a reference to three Objects GoodFilterer, BadFilterer and UnrecognizedFilterer. Each of them contains the following methods: addMethod(MyObject object), getObjects() and addFilter(). Of course they have to implement an interface Filterer.
With the addFilter method you can build the chain. so that the GoodFilterer contains a reference to the BadFilterer and this one contains a reference to the UnrecognizedFilterer
Now you go through your list of MyObjects and call the add method on the GoodFilterer (first one in this chain). Inside the add method you decide if this is good, than you keep it and finish the work, if not pass it on to the BadFilterer.
You keep your three methods for getting the good/bad and unrecognized, but you will pass this to the getObjects() method of the corresponding Filterer
The Benefit is that the logic if this is a good/bad or Unrecognized one is now seperated.
The Downside you would need 3 new classes and 1 Interface.
But like i said, this is just an other idea what you could do.
You should simplify as it's possible. Just make static method in MyObjectFilter with following signature:
public static List filterMyObjects(List data, Group group).
Group is enumeration with three values and it can be used as attribute of MyObject class
I might try something like:
enum MyObjectStatus {
GOOD, BAD, UNRECOGNIZED;
}
class MyObjectFilterer {
private MyObjectStatus getStatus(MyObject obj) {
// classify logic here, returns appropriate enum value
}
// ListMultimap return type below is from Google Guava
public ListMultimap<MyObjectStatus, MyObject> classify(List<MyObject> objects) {
ListMultimap<MyObjectStatus, MyObject> map = ArrayListMultimap.create();
for(MyObject obj: objects) {
map.put(getStatus(obj), obj);
}
}
}
Call classify() to get a Multimap, and extract each category as needed with something like:
List<MyObject> good = map.get(GOOD);
List<MyObject> bad = map.get(BAD);
List<MyObject> unknown = map.get(UNRECOGNIZED);
A nice thing about this solution is you don't have to create/publish accessor methods for each category (unless you want to), and if new categories are created, you also don't add new accessors -- just the new enum and the additional classifier logic.
My problem is this; I have to order a table of data. Each row of the table is an object (lets call it TableObject) stored in a List. Each column of data is a property of the class (usually a String).
I have to do the typical ordering of data when the user clicks on any column. So I thought about changing the List to a TreeSet and implementing Comparator in my TableObject.
The problem comes when I try to reorder the TreeSet. The compare is fairly easy at first (cheeking for exceptions in parseInt have been omitted):
public int compare(TableObject to1, TableObject to2){
TableObject t1 = to1;
TableObject t2 = to2;
int result = 1;
if(Integer.parseInt(t1.getId()) == Integer.parseInt(t2.getId())){result=0;}
if(Integer.parseInt(t1.getId()) < Integer.parseInt(t2.getId())){result=-1;}
return result;
}
But when I have to reorder by the text of the data or by other dozens of data that the TableObject has I have a problem.
I do not want to create dozens of compare functions, each for one. I prefer not to use a switch (or a chain of ifs) to decide how to compare the object.
Is there any way to do this in some way (like Reflexive), that doesn't imply that I will write like hundreds of lines of nearly the same code?
Thanks for all!
Bean Comparator should work.
Using reflection the BeanComparator that will allow you to sort on any property that has a zero parameter method that returns the value of the property.
So basically you can sort on any property that has a "getter" method.
What you could do is make the comparator take a String representing the name of the parameter to sort by in its constructor.
Then you could use reflection to sort by the given parameter.
The following code is very dirty. But I think it illustrates the gist of what you would need to do.
public class FieldComparator<T> implements Comparator<T> {
String fieldName;
public FieldComparator(String fieldName){
this.fieldName = fieldName;
}
#Override
public int compare(T o1, T o2) {
Field toCompare = o1.getClass().getField(fieldName);
Object v1 = toCompare.get(o1);
Object v2 = toCompare.get(o2);
if (v1 instanceof Comparable<?> && v2 instanceof Comparable<?>){
Comparable c1 = (Comparable)v1;
Comparable c2 = (Comparable)v2;
return c1.compareTo(c2);
}else{
throw new Exception("Counld not compare by field");
}
}
}
Yes, you could use the reflection API, to get the content of a field based on it's name.
See Field class and especially the Field.get method.
(I wouldn't recommend it though, as reflection is not designed for this type of task.)