I have implemented my own ComboBoxModel:
public class MyComboBoxModel extends AbstractListModel<MyType>
implements ComboBoxModel<MyType> {}
Now I obviously need to override public void setSelectedItem(Object item), but the documentation says the following:
The implementation of this method should notify all registered ListDataListeners that the contents have changed.
To do so, I guess I need to use the method AbstractListModel.fireContentsChanged(Object, int, int). The Problem with JComboBox is, that one can set the selected item without it having to be in the list, so when setSelectedItem(Object) is called, I cannot necessarily determine the index of the item in question, since it need not be in the underlying model.
I found an answer to another question (https://stackoverflow.com/a/7077192) which uses fireContentsChanged(item, -1, -1) in this case, but the person did not provide any details to that part of code. Now I am wondering, whether this was the correct way to deal with a changed selected item?
Should I ALWAYS use -1 as both indexes? Should I try and get the real index of an item, if it is actually in the model? Or should I do something entirely different?
Related
Suppose I have a private ArrayList or a LinkedList inside a class, that I will never assign new reference to it, or in other words this will never happen:
myLinkedList = anotherLinkedList;
So that I won't need to use setMyLinkedList(anotherLinkedList).
But! I need to add elements to it, or remove elements from it.
Should I write a new kind of setter to only, do the task of adding instead of setting, like myLinkedList.add(someElement)?
Or it is OK to do this by using getter, without disobeying Encapsulation principal?
getMyLinkedList().add(someElement)
( + Suppose I am going to lose my mark if I disobey encapsulation :-")
I don't think it a particularly great practice to do something like:
myObj.getMyList().add(x);
since you are exposing a private class variable in a non read only way, but that being said I do see it pretty frequently(I'm looking at you, auto generated classes). I would argue that instead of doing it that way, return an unmodifiable list and allow users of the class to add to the list via an explicit method:
public class MyClass{
private final List<String> myList = new ArrayList<String>();
public List<String> getList(){
return Collections.unmodifiableList(this.myList);
}
public void addToList(final String s){
this.myList.add(s);
}
}
EDIT After reviewing your comments, I wanted to add a bit about your setter idea:
I meant using that line of code inside a new kind of setter inside the class itself, like public void setter(someElement){this.myLinkedList.add(someElement);}
If I'm understanding you correctly, you are saying you want to expose a method that only adds to your list. Overall this is what I think you should be shooting for, and what many have outlined in the answers, however, labeling it as a setter is a bit misleading since you are not reassigning (setting) anything. That, and I strongly recommend returning a read only list from your getter method if possible.
I would suggest in this case it would be best to follow your Encapsulation principals and use a method for adding elements to the list. You have restricted access to your list by making it private so that other classes cannot directly access the datatype.
Let the class that stores your ArrayList have direct access to the list, but when other classes want to add to the list, use an add() method.
In general, you should not assume that the list being returned by the getter is the original one. It could be decorated or proxied for example.
If you want to prevent that a new list is set on the target object, you could define an add method on the target class instead.
As soon as you have a Collection of any kind, it is generally not a bad idea to add methods like add(), remove() to the interface of your class if it makes sense that clients can add or remove objects from your private list.
The reason why it is useful to have these extra methods implemented (it might seem like overkill, because after all those methods mostly just call the method on the Collection) is that you protect evil clients from doing things to your list you don't want them to do, because the interface of most Collections contain more than just the add() and remove() methods and mostly, you don't want clients to be messing around with things you can't control. Therefore the encapsulation principle is that important to your teacher.
Another plus: if at any time, you would decide that a certain condition must be met when an object is added to your list, this can easily be implemented in the method you already have. If you give a client access to the direct reference of your list, it is not easy at all to implement this kind of things (which are not rare).
Hope this helps
So you have a class containing a List field (it should be final, since you don't intend to assign to it), and you want to allow callers to add to the List, but not be able to replace it.
You could either provide a getter for the list:
public List<E> getMyList() {
return myList;
}
Or provide a method to add to that list:
public void addToMyList(E e) {
myList.add(e);
}
Both are valid design decisions, but which you use will depend on your use case. The first option gives callers direct access to the List, effectively making it public. This is useful when users will be modifying and working with the list repeatedly, but can be problematic as you can no longer trust the List is in any sort of reliable state (the caller could empty it, or reorder it, or even maliciously insert objects of a different type). So the first option should only be used when you intend to trust the caller.
The second option gives the caller less power, because they can only add one element at a time. If you want to provide additional features (insertion, add-all, etc.) you'll have to wrap each operation in turn. But it gives you more confidence, since you can be certain the List is only being modified in ways you approve of. This latter option also hides (encapsulates) the implementation detail that you're using a List at all, so if encapsulation is important for your use case, you want to go this way to avoid exposing your internal data structures, and only expose the behavior you want to grant to callers.
It depends on the application - both are acceptable. Take a good look at the class you're writing and decide if you want to allow users to directly access the contents of the list, or if you would prefer that they go through some intermediate process first.
For example, say you have a class ListEncrypter which holds your MyLinkedList list. The purpose of this class is to encrypt anything that is stored in MyLinkedList. In this case, you'd want to provide a custom add method in order to process the added item before placing it in the list, and if you want to access the element, you'd also process it:
public void add(Object element)
{
MyLinkedList.add(encrypt(element););
}
public Object get(int index)
{
return decrypt(MyLinkedList.get(index););
}
In this case, you clearly want to deny the user's access to the MyLinkedList variable, since the contents will be encrypted and they won't be able to do anything with it.
On the other hand, if you're not really doing any processing of the data (and you're sure you won't ever need to in the future), you can skip creating the specialized methods and just allow the user to directly access the list via the get method.
I'm trying to write a code for a method which has certain conditions which needs to be met. I believe that I need to use methods from a different class to meet the conditions. I've done the last 2 conditions but I have got no clue on how to go about the others because I do need to access methods from a different class.
It seems like using the shtlCode, you can obtain the proper Shuttle instance from your shuttleMap, like so:
public boolean canTravel(int pCardId, String shtlCode)
{
Shuttle shuttle = shuttleMap.get(shtlCode);
...
Once you have the Shuttle, you can then find the Asteroid it's currently on:
Asteroid currentShuttleAsteroid = shuttle.getSourceAsteroid();
Having these two objects, it's up to you to ensure the conditions have been properly met. (And also, to ensure that your shuttleMap contains a Shuttle with the code specified, etc.)
As Craig suggested above, keep the Shuttle that you fetched from the hashmap. You will need it to implement most of the remaining checks.
canTravel is given a card id, but is going to need the PearlCard itself. But where to get it from? Three possibilities:
The caller can pass a PearlCard into canTravel instead of the integer ID, if it has it.
canTravel could search for a PearlCard with the matching ID in the source asteroid's list of PearlCards. (And if it's not in there, then you can't travel anyway.)
Or you may want to add a HashList of all PearlCards to your program, similar to shuttleMap.
Then get the shuttle's destination asteroid and see if has room for one more PearlCard (compare PearlCard list's length to the asteroid's capacity). Also check to see if the card has enough credit and rating for that asteroid. (You didn't show PearlCard class so I don't know the exact code, but I'm guessing you'll have no trouble with that part.)
Note: your current code seems to have at least one bug. canTravel searches the asteroid list for the card ID. Like I said above you will need to get the card from somewhere, but it's not going to be in asteroidList.
Is it possible to detect whether a node is expanded or collapsed from within SwingX's TreeTableModel/AbstractTreeTableModel (specifically the getValueAt(Object node, int index) method)? I need to display different values for a parent node, depending on whether it's expanded or collapsed. (I realize this violates the principle of separating model and view, sorry!)
I know you can check this from the JXTreeTable object, using the standard isExpanded() and isCollapsed() methods, but I need to know this from within the model.
Specifically, I have objects which have multiple versions, and I'd like to use JXTreeTable to support expanding/collapsing the versions. If the object is collapsed, I want the parent node to display a summary of the values across all versions. If it's expanded, I want the parent to display only the values for the current version, (the most important one), and a summary is no longer needed or desired.
Some pseudo-code to give you an idea of what I mean:
getValueAt(Object node, int index) {
if (node.hasChildren()) {
if (node.isExpanded()) { // this is the part I'm not sure how to implement
return node.getCurrentValue(); // eg "Current version: C"
}
else {
return node.getSummaryValue(); // eg "Current version: C; previous versions: A, B"
}
}
else {
return node.getValue(); // eg "Version: B"
}
}
EDIT
Thank you camickr, you're of course right that my question is invalid! (I feel a bit stupid now.)
Would you suggest using a custom TreeCellRenderer, such that it selects which value to display based on the expansion state of the node? That is, have the model provide an object that implements something like this:
public interface ExpansionStateDependentValue {
public Object getDisplayValue(boolean expanded);
}
and then have the TreeCellRenderer use this method (assuming the cell value implements the interface) to display the appropriate value based on the expanded flag in the getTreeCellRendererComponent() method?
but I need to know this from within the model.
A Model can be shared by many View component. That is it could be used by two different JTree Objects. So it is possible that a node code be expanded in one view of the tree but not in the other.
So the answer to your question is that the Model does not contain this information because it is a function of the view. So your approach of trying to do this in the model is not correct.
I'll write down the whole problem first.
A ring is a collection of items that has a reference to a current item. An operation -- let's call it advance--moves the reference to the next item in the collection. When the reference reaches the last item, the next advance operation will move the reference back to the first item. A ring also has operations to get the current item, add an item, and remove an item. The details of where an item is added and which one is removed are up to you.
Design an ADT(Abstract Data Type) to represent a ring of objects. Specify each operation by stating its purpose, by describing its parameters, and by writing a pseudocode version of its header. Then write a Java interface for a ring's methods. Include javadoc-style comments in your code.
So is it saying the Ring is like a class with operation that can move items by using a reference variable like T = items? And Advance would change T to represent a different item each time it's being called? Something like in UML format....
ADT: Ring
+advance(): T // move T to next item in collection and if T reaches last item, move T back to the first item.
+getCurrItem(): T // return item that T reference.
+addItem(item T): void // add an item in for T, No return.
+removeItem(Item: T): boolean // remove item that T reference and return true | false if it succeed or not.
Am I on the right track or am I supposed to do something else?
That looks like a good start to me. Now you have to work on designing the ADT and how you suppose you will store items and reference the end to the beginning. This is a data abstractions problem, and you can approach the implementation in several ways, but it's up to you to design it in an efficient way.
I need a value of Someclass based on the key. And the key can be a string, boolean, or another Object, that's why I used Object as key. But I have a problem, when the object is a string. and I have two Object of string, which is equals, but it should return different value, because it is a different object.
The code that I have:
Object k = new String("action");
Object l = new String("action");
Hashtable<Object,SomeClass> map = new Hashtable<Object, SomeClass>();
map.put(k,anObject1);
map.put(l,anObject2);
map.remove(k); // it is removing both with k and l.
when I check the hashCode() of both object, it returns the same value, which is ultimately what not I want.
Is there any solution of this? Is I need to make a new class that override Equals() of object? but, still, the hashCode. :( The problem is I need a hashCode that return different value for different Object.
Edited:
I am doing this because I need to do different action based on what the string is, but the action will differ by the value returned by map with the key.
Updated:
Okay, here is all the story why I need this weird thing.
I have a player instance, and 3 land instances. So I wanted the player to plow land1, land2, land3. If the player wanted to plow a land, that land make a running thread, that tell the player to move to position X, and do the job action, and wait() by object action, and when the other thread notify this thread by object action, the land then modify itself. The player then make an animation based on the object action. I am having ArrayList<Position> destination and 'ArrayList action` to have it. Maybe you can read my other question about this here.
So I wanted to make the action cancelable. I implements it by also passing the action object. I have a button that show for every action, and every button will cancel that action. I passing the action here too. So when I click the button, the land will get the notify. The problem is I can't make the ArrayList<Position> remove the destination by the Action, because it's don't know where the index. I'm new to Java but have been using C++ a lot, so I thinking of using Hashtables, because it's O(1) differs with C++ O(log n), and kind of convenience because not many changes to my current code.
Is it understandable?
You could use an IdentityHashMap instead, though it might help if you could explain what exactly you're trying to do here. This is not a terribly common requirement and unless you have some very good reasons you want to do this, there's probably something else you're better off doing.
By the way, a Map can only hold one value for a single key. So after your second call to map.put, the first value you put in there is already gone.
Edit:
Ok, I've read your explanation and... well, I'm still not completely clear on what you're doing. Here's my best guess from what you've said:
You have an action called "plow", represented as a String.
You are telling the player to "plow" 3 different lands.
You want to be able to cancel that action for one land without cancelling it for the others.
To do this, you're trying to map 3 different instances of the String "plow" to the Positions of the 3 different lands.
If this (or something like it) is what you're trying to do, here are my thoughts:
The action String should not be unique... "plow" is "plow", whatever land it is done on. What is unique is the combination of an action like "plow" and the land that action is to be done on.
Given that, "plow" should be considered something like an "action type". It might be good to use an enum or some such to represent action types.
An Action class should contain an "action type" and a Position. When you click to cancel that Action, you have the data you need right there.
The String class overrides equals() and hashCode() such that two Strings with the same characters have the same hashCode() and are equal. But the Object class itself has an equals() method that never returns true for two different objects. It's actually not necessary (nor possible!) for hashcodes to be unique; they just have to be nicely distributed across the range of possible values.
So in any case: String is ill-suited for your requirements, I agree; but an object of any other class that doesn't override equals() and hashCode() should be just fine.
This is the very semantics for a Hashmap: keys are uniqe and each value from the key domain maps to at most one value in the Hashmap.
Think of it like an array, only that the array is not indexed by numbers but by arbitrary objects. You can't have more than one different value at the same index in an array.
You might consider creating your own class to represent a Key and define your own hashcode by some unique identifier .. perhaps using a AtomicLong