Good practice to avoid ConcurrentModification of static collection - java

Consider class of Player... when player joins the game (object is created), it checks for player with the same name already joined...
public class Player {
private static List<Player> players = new ArrayList<>();
private String name;
public Player(String name) {
this.name = name;
for (Player otherPlayer : players) { // Iterating static field
if (otherPlayer.name.equalsIgnoreCase(name)) {
otherPlayer.quit("Somebody with the same name joined the game");
}
}
}
public void quit(String message) {
players.remove(this); // Modifying static field
Server.disconnect(this, message);
}
}
I know that Iterator can deal with this problem, but we don't always know what happens with public static fields in foreign methods and when to use foreach and when to use Iterator instead...
Is there any good practice for this problem?

The first, and more important good practice is called separation of concerns. As in: the Player class should model a single player.
You are mixing the responsibility of being a Player and managing the overall set of Player objects in one place. Don't do that!
These two things simply don't belong together. In that sense: there should be a PlayerManager class for example that knows about all players. And also forget about using a static field like this. Because that creates super-tight coupling between the different aspects of your class. What happens for example when you need more than one list of players? What if you have so many players that you want to organize them in buckets, based on certain properties?
Beyond that, the direct answer is: instead of immediately deleting objects from your list - collect them into a second playersToBeDeleted list. And after iterating the first list, simply use players.removeAll(playersToBeDeleted) for example.
And talking about good practices: carefully consider if you really want to use Lists - or if Set wouldn't be the better alternative. Lists always imply order, and yuck, they allow to repeatedly add the same object. Whereas a Set gives you "unique elements" semantics for free!

I see that you are trying to call list.remove(entry) method while still inside the for-each block. Don't do that.
Use Iterator instead of the for-each construct when you need to:
Remove the current element. The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
Iterate over multiple collections in parallel.
Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

Related

Is switching between Collections worth it?

Java offers us Collections, where every option is best used in a certain scenario.
But what would be a good solution for the combination of following tasks:
Quickly iterate through every element in the list (order does not matter)
Check if the list contains (a) certain element(s)
Some options that were considered which may or may not be good practice:
It could be possible to, for example, first use a LinkedList, and
then convert it to a HashSet when the amount of elements
is unknown in advance (and if duplicates will not be present)
Pick a solution for one of both tasks and use the same implementation for the other task (if switching to another implementation is not worth it)
Perhaps some implementation exists that does both (failed to find one)
Is there a 'best' solution to this, and if so, what is it?
EDIT: For potential future visitors, this page contains many implementations with big O runtimes.
A HashSet can be iterated through quickly and provides efficient lookups.
HashSet<Object> set = new HashSet<>();
set.add("Hello");
for (Object obj : set) {
System.out.println(obj);
}
if (set.contains("Hello")) {
System.out.println("Found");
}
Quickly iterate through every element in the list (order does not matter)
It the order does not matter, you should go with a Collection implementation with a time complexity of O(n), since each of them is implementing Iterable and if you want to iterate over each element, you have to visit each element at least once (hence there is nothing better than O(n)). Practically, of course, one implementation is more suited compared to another one, since more often you have multiple considerations to take into account.
Check if the list contains (a) certain element(s)
This is typically the user case for a Set, you will have much better time complexity for contains operations. One thing to note here is that a Set does not have a predefined order when iterating over elements. It can change between implementations and it is risky to make assumptions about it.
Now to your question:
From my perspective, if you have the choice to choose the data structure of a class yourself, go with the most natural one for that use case. If you can imagine that you have to call contains a lot, then a Set might be suited for your use case. You can also use a List and each time you need to call contains (multiple times) you can create a Set with all elements from the List before. Of course, if you call this method often, it would be expensive to create the Set for each invocation. You may use a Set in the first place.
Your comment stated that you have a world of players and you want to check if a player is part of a certain world object. Since the world owns the players, it should also contain a Collection of some kind to store them. Now, in this case i would recommend a Map with a common identifier of the player as key, and the player itself as value.
public class World {
private Map<String, Player> players = new HashMap<>();
public Collection<Player> getPlayers() { ... }
public Optional<Player> getPlayer(String nickname) { ... }
// ...
}

Should I implement List interface or extend ArrayList class

I am developing an application where as a background I need to monitor the user activity on particular objects and later when they are visualized they need to be sorted based on the order of which the user used them ( the last used object must be visualized on the first row of a grid for example.)
So if I have an ArrayList where I store the objects which the user is dealing with in order to add the last used object I need to check if it is already in the list and then move it at the first position. If the object is not there I simply add it at the first position of the list.
So instead of doing all these steps I want to make my own list where the logic explained above will be available.
My question is which scenario is better:
Implement the list interface
Extend the ArrayList class and override the ADD method
Create a class that contains an ArrayList and handles any additional functionality.
I.e. prefer composition over inheritance (and in this case, implementing an interface). It's also possible to have that class implement List for relevant cases and just direct the (relevant) operations to the ArrayList inside.
Also note that LinkedHashMap supports insertion order (default) and access order for iteration, if you don't need a List (or if you can suitably replace it with a Map).
So instead of doing all these steps i want to make my own list where
the logic explained above will be available.
I would try to refactor your design parameters (if you can) in order to be able to use the existing Java Collection Framework classes (perhaps a linked collection type). As a part of the Collections Framework, these have been optimized and maintained for years (so efficiency is likely already nearly optimal), and you won't have to worry about maintaining it yourself.
Of the two options you give, it is possible that neither is the easiest or best.
It doesn't sound like you'll be able to extend AbstractList (as a way of implementing List) so you'll have a lot of wheel reinvention to do.
The ArrayList class is not final, but not expressly designed and documented for inheritance. This can result in some code fragility as inheritance breaks encapsulation (discussed in Effective Java, 2nd Ed. by J. Bloch). This solution may not be the best way to go.
Of the options, if you can't refactor your design to allow use of the Collection classes directly, then write a class that encapsulates a List (or other Collection) as an instance field and add instrumentation to it. Favor composition over inheritance. In this way, your solution will be more robust and easier to maintain than a solution based on inheritance.
I think LinkedHashMap already does what you need - it keeps the elements in the order they were inserted or last accessed (this is determined by the parameter accessOrder in one of the constructors).
https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html
EDIT
I don't have enough reputation to comment, so I'm putting it here: You don't actually need a map, so Venkatesh's LinkedHashSet suggestion is better.
You can do something like this:
<T> void update(Set<T> set, T value) {
set.remove(value);
set.add(value);
}
and then
LinkedHashSet<String> set = new LinkedHashSet<>();
update(set, "a");
update(set, "b");
update(set, "c");
update(set, "a");
Iterator<String> it = new LinkedList<String>(set).descendingIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Output:
a
c
b
You might try using HashMap<Integer, TrackedObject> where TrackedObject is the class of the Object you're keep track of.
When your user uses an object, do
void trackObject(TrackedObject object)
{
int x = hashMap.size();
hashMap.add(Integer.valueOf(x), object);
}
then when you want to read out the tracked objects in order of use:
TrackedObject[] getOrderedArray()
{
TrackedObject[] array = new TrackedObject[hashMap.size()];
for(int i = 0; i < hashMap.size(); i++)
{
array[i] = hashMap.get(Integer.valueOf(i));
}
return array;
}
A LinkedHashSet Also can be helpful in your case. You can keep on adding elements to it, it will keep them in insertion order and also will maintain only unique values.

Array vs. ArrayList when position is important

I'm a Java newbie with a quick Array vs. ArrayList question. I have an array of objects that can grow or reduce in size, but it's very important for me to maintain the position they were in relative to each other in the array. I'm thinking because of this I need to use Array instead of an ArrayList which can condense/shift elements around if they are removed/added.
The practical example: In my first Java application that I'm slugging through to learn the nuances of this language I'm making a basic poker game simulator. I have Player objects in an array representing the seats they are sitting at, and it's important to know where the dealer button (index) was placed before rotating it. Players being removed or added from an ArrayList will change the indices of the players, and that can throw off the next Player to get it. Dealer button movement is very player-placement specific.
Long story short - is using an Array the best way of handling elements in an array-type structure that need to maintain their position in the array? Is there a better method or logic to accomplish this? I apologize for the simple question but I couldn't find any other alternatives and wanted to confirm that this is the best route to take.
EDIT:
To further clarify, let me give an example of why ArrayList's element movement won't work:
Take three players and their indices in the array:
0 : Player One (Dealer button)
1: Player Two
2: Player Three
If player two (index one) gets up from the table before the dealer button is rotated, depending on the rules player one will keep the button and the blinds will be adjusted accordingly (there's other variants of this rule, but the one I like to use). In an ArrayList, the internal array will be condensed and player three will end up getting the button an extra round before he should. I need to track the empty seat that was active during the hand but was emptied before the round was over and the button moved.
I'm starting to realize that the concept of a "seat" is going to be more complicated, I need to track state on it, including "player just sat down while hand in progress," "player got up while hand in progress," etc. #Stephen P - I think you're right about this, I'm going to need to track them separately and cannot use a simple array structure to determine the logic. Timing of when the elements are added and/or removed is paramount to the application logic, and simply examining if an element is there or not won't cut it.
For the Seats themselves, I'm learning towards ArrayList since the Seats will now always be there, no empties. The Seat will just have a reference to the Player object if one is sitting there as well as WHEN that player arrived. Thanks everyone!
With ArrayList, you can make your players sit tight by using set(int index, T value). You just have to fill the arrayList with nulls first:
List<Player> seats = new ArrayList<>(Collections.nCopies(numPlayers,(Player)null));
seats.set(2,player); // Place a player in the third chair
seats.set(1,null); // Empty the second chair
Long story short - is using an Array the best way of handling elements
in an array-type structure that need to maintain their position in the
array? Is there a better method or logic to accomplish this? I
apologize for the simple question but I couldn't find any other
alternatives and wanted to confirm that this is the best route to
take.
Position shouldn't be your most important criterion for choosing array vs. ArrayList, at least I don't believe it should be.
Arrays are covariant, and more performant most of the time. They mix poorly (if at all) with Java generics which is really kind of a big deal a lot of the time. You cannot create a reference to a new instance of an array of a non-reifiable type (though you can receive one, but buyer beware).
ArrayLists, as a part of the Java Collections API, are invariant. For this reason they work much better with Java generics and, according to Joshua Bloch (Essential Java, 2nd Ed), should be favored much of the time. ArrayLists should often be less performant (and less concise) than arrays. Moreover, as part of the Java Collections API, ArrayLists are more flexible because they extend the List interface which enables you to change implementations from ArrayList to any other List provided that your own class that implements the List is well encapsulated (i.e. the ArrayList is not part of your class's exported API).
There are other differences, of course, but these are the ones that really stand out. If you were really concerned about performance, you could create your own List implementation that was backed by arrays (like ArrayList is) in order to get a feature or the API contract you really wanted. Otherwise, to me, it sounds like you should be using ArrayList (or even other Collection type such as Map (suggested)).
If you have a constant number of seats, you can use either an array or an ArrayAist. If you want to increase the number of seats, you will need an Arraylist, because regular arrays are immutable. See this for more information on the immutability of arrays: Why is an array's length immutable? An ArrayList will never move around its contents if you only use the get(int index) and set(int index, E element)
Also, it is bad practice to let null mean something, even if that something is nothing.
The code:
seat ArrayList initialization
List<Person> seats = new ArrayList<Person>(max_Number_Of_Seats_here);
for(Person person : seats)
{
person = new Person("");
}
//You can then set people like this:
seats.set(seat_index_here, new Person("Darkprozac"));
And have the parameter for the constructor for the class Person be its name.
Person constructor
...
public String name;
public Person(String name)
{
this.name = name;
...
You can then check if the Person's name is "", and if it is, skip that person:
Check if seat is empty
...
for(Person person : seats)
{
if(person.name.equals(""))
{
//do nothing
}
else
{
doSomething();
}
}
...
You can also wrap a Person in a Seat class:
Seat Class
public class Seat
{
public Person person;
public String state;
public Seat(String name)
{
if(name.equals("");
{
state = "empty";
}
else
{
state = "full";
person = new Person(name);
}
}
}
and then modify seat ArrayList initialization and Check if seat is empty accordingly.
Thanks to MrBackend for pointing out that I was wrong about ArrayLists initializing as null.
I would use a map, specifically, a TreeMap.
NavigableMap<Integer, Player> seats = new TreeMap<Integer, Player>();
Integer first = seats.firstKey();
Integer next = seats.nextKey(first);
This gives the benefits of a map, you don't have to worry about seats shifting (even accidentally), and you can still navigate seats easily.
The map manages its own storage (unlike an array) and does not have a risk of shifting indices (unlike an ArrayList).

List handling inside a class

Let's say I have a class A that has a list of related elements (type of elements not relevant):
public class A {
private List<String> list;
public List<String> getList() {
return list;
}
public void addElement(String element) {
list.add(element);
}
}
Now I want access to this list from another class, Client. I need to add a new element. The question, a more phylosophical one, is how best is this done from a design point of view.
public class Client {
private A a = new A();
public void method1() {
a.getList().add("");
}
public void method2() {
a.addElement("");
}
}
If anyone could point out any advantage of any of these methods, would be much appreciated.
Thanks.
Generally your getList() method is considered bad style. If class A returns a reference to its actual List, than a caller might call clear() on that list, or add a million elements to it, or so who-knows-what-all. It's a much better idea to return only an Iterator, or only a read-only view of the List using Collections.unmodifiableList().
This means your solution 2, addElement() is better; the addElement() method might contain code to validate the added elements, limit the size of the list, or whatever. And clear() would not be accessible.
If your intention is to really expose the list, method2 is usually a better OOP-style. (Since by using method2 you'll get addAll etc for free.)
Examples of this pattern in the standard API:
HashMap.keySet
Subject.getPrincipals
The documentation should take care to say something like The object is backed by the returned collection, so modifications will ...
The drawback is that by exposing the list you allow clients to do remove and so on, so if your intention is to just collect items through add then method1 may still be a better choice.
Examples of this pattern in the standard API:
Component.addKeyListener
DefaultTableModel.addRow
I wouldn't give access to the list (i.e. getList()) its good however that you added a addElement method. That is a good idea because you can put restrictions on what can be added to the list in that method.
I would choose
public void method2() {
a.addElement("");
}
Because mantains hidden the list inside A. Of course this depends on how related is the list to A if only instances of A should get a reference to the list then this is my choice.
One other reason might be that giving away the list could lead to clients removing items, you might want to avoid clients to consider the list as their own, it's A's, keep it safe! :P
Otherwise the list does not belong to A and should be removed from it.
You should most definitely hide the underlying list in class A. A should not provide a getList() method if possible.
Class B should use a.addElement() exclusively. And, if B needs to read from the list in A, A should provide methods for accessing the list instead of giving B the entire list.
One of the main tenants of OO programming is Encapsulation. Which means that you should hide the underlying implementation of your classes, and abstract out that low-level info.
To your specific question, you will want to use method2(). You shouldn't even be able to use a.getList() from class B if you are following proper OO principles.
When coding, you should consider the maintenance process. The less the classes know about each other the better it it is.
The client should only know that A can have elements .... so I will consider the second design as being much better.
You should provide a method for adding element on class A. Returning the original List is wrong from the design point of view because the user of your class has full access to it.
method2 is better because the client doesnt need to bother with the list implementation. if class A changes its data structure, the client is not affected.

Changing parameters in a LinkedList

I'm new to java so im having some "annoying" problems. I have a class Employee which contains an int idNumber and a int phone number. Then I have a LinkedList<Employee> sorted by idNumber. I want to change the phonenumber of a certain idnumber.
I've been working with Iterators but i don't know if i'm doing it right, which I doubt.
public void setNewPhoneNumber(int idnumber, int newphone){
Iterator<IndexC> it = listEmployee.iterator();
IndexC employeeTemp = null;
boolean found = false;
while(it.hasNext() && !found){
employeeTemp = it.next();
if(employee.getIdNumber()== idnumber){
employeeTemp.setNewPhoneNumber(newphone);
found = true;
}
}
}
Yeah, I know employee.setNewPhoneNumber is wrong, but I don't know which the correct way change the value on the linkedlist. (Sorry for the bad english, not a native speaker)
Iterators are a pain; the foreach construct is a lot nicer:
public void setNewPhoneNumber(int idnumber, int newphone) {
for (Employee employee : listEmployee)
if (employee.getIdNumber() == idnumber) {
employee.setNewPhoneNumber(newphone);
return;
}
}
I'm not clear on what IndexC is, and I don't often use LinkedList - there could be some subtlety here I'm missing - but I think you're better off avoiding the iterators.
You're not "changing parameters in a Linked List", you're trying to find an object in a list and change a property of that object
You should be using a Map (such as a
HashMap) instead of a List, then you
won't have to iterate.
If you iterate, use the for loop: for(IndexC employeeTemp: employeeTemp){}
Changing the phone numer would conventionally be done through a setPhoneNubmer() method, but it depends entirely on the IndexC class whether it has such a method. Look at that class's definition.
When asking a question, always include error messages! "It doesn't work" is a really useless piece of information.
my bad, IndexC is the Employee class, "bad copy past" sorry. I don't like LinkedList but i have to use it with +5000 entries (School Exercise). I don't think using for's with so many entries is recommended.
The class as set's, get's, clones..
class Manager{
private LinkedList<Employee> listE = new LinkedList<Emploee>;
public void setNewPhoneNumber(int idnumber, int newphone)
}
One reason for it not to work is that there´s no IndexC in the list that satisfies (employee.getIdNumber()== idnumber).
Maybe you should post some extra code, for example, where is that list created, have you filled it with anything?
Besides, what is it that doesn´t work? The setting of the new phone number, or retrieving the element from the list?
In both cases, i think that you should post both methods, that is
getIdNumber();
As Mike B. says, maybe using a Map implementation would be better. Since you are considering order, maybe a SortedMap (such as TreeMap) implementation could be better.
In any case, rember you have to override two methods in your IndexC (when using maps). Otherwise, things will get messy.
equals
hashCode
http://java.sun.com/j2se/1.4.2/docs/api/java/util/LinkedList.html
You want to use a for loop with an int incrementing till you find the object you want. Then you want to use listEmployee.get() to get the object you want and edit it.
However, if you need random access to items like that, then you should not be using Linkedlists. Stick it in an ArrayList instead. That has much better random access time.
As a side note, you don't even need the for loop if the id numbers are in order from 0-whatever. You can simply listEmployee.get(idNumber)

Categories

Resources