I'm not sure if this is a duplicat or not (it probably is) but I can't find what I'm looking for.
I have a static ArrayList holding objects created from a constructor in that class, or any class extending it:
public static ArrayList<Person> PersonList = new ArrayList<>();
public Constructor(....){
PersonList.add(this);
}
Now I'm trying to delete objects from this arraylist by using index, but I'm getting ArrayIndexOutOfBounds: Array index out of range: (index).
Now I know this error is telling me there is no element in the specified position, but then I don't understand why PersonList.size() returns 4 (if there are 4 elements in the list).
I'm new to java, so I hope anyone here can help me. Here's the code:
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
if(SwingUtilities.isRightMouseButton(arg0)) {
try {
Person.PersonList.remove(list.getSelectedIndex());
list.remove(list.getSelectedIndex());
}catch (Exception e) {
System.out.println(e);
}
System.out.println("Index: " + list.getSelectedIndex());
updateData();
}
}
});
I'm confused by this:
public Constructor(....){
PersonList.add(this);
}
It looks like every time you create a new object of that class (a Person I'm assuming) you are adding it to a class variable list. I'm assuming that every time you create a new instance of that class, it's resetting the global list. Can you confirm that PersonList is not always size = 1? I'm suspecting it is, so move that list to a different class
Okay so after testing a little it seems it works just fine after all. It throws an error telling me its out of bounds, but after updating the .size() after each deletion, it decreases.
Though I have no clue why it works if it tells me it doesn't?
Related
In Java we can not reassign a reference inside a method.
So the following does not work:
class SomeClass {
List<PaidOrders> paidOrders;
List<PendingOrders> pendingOrders;
List<CancelledOrders> cancelledOrders;
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist = newOrders;
}
}
But the following does work:
class SomeClass {
private void process(List<OrderStatus> data, List<Orders> currentOrderlist) {
List<Order> newOrders = fromOrderStatus(data);
currentOrderlist.clear();
currentOrderlist.addAll(newOrders); // <- extra linear loop
}
}
The problem is that the second example does an extra linear loop to copy from one list to the other.
Question:
I was wondering, is there some design approach so that I could neatly just replace the references instead? I.e. somehow make the first snippet work with some change in the parameters or something?
Update
After the comments I would like to clarify that the currentOrderList can be any of the paidOrders, pendingOrders, cancelledOrders.
The code for process is the same for all types.
Hm. I see two possibilities here. Either you use some wrapper object such as AtomicReference (might be a bit overpowered because of the multi-threading issues) as the argument and then just set it there or you use a consumer.
In the second case your method would look like this:
public void process(List<OrderStatus> data, Consumer<List<Orders>> target) {
List<Person> newOrders = fromOrderStatus(data);
target.accept(newOrders);
}
Then on the calling side you would implement it like this:
process(data, e-> <<targetList>> = e);
If your list will be wrapped by a different object (for example - AtomicReference), then you will be able to change it.
public static void doSomething(AtomicReference<List<Integer>> listAtomicReference){
List<Integer> newIntegers = new ArrayList<>();
listAtomicReference.set(newIntegers);
}
public static void main(String[] args) {
AtomicReference<List<Integer>> listAtomicReference = new AtomicReference<>(Arrays.asList(4));
doSomething(listAtomicReference);
System.out.println(listAtomicReference.get());
}
Output:
[]
Making a public member variable in a class.
With that being said, I wouldn't recommend walking this path.
Is premature optimization really the root of all evil?
I'm trying to do a swing application which adds names to an ArrayList and then displays it in Jcombobox.I already did the window and everything but I can't seem to get the hang off detecting duplicate names.
I tried
btnnext.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
if(checkDuplicate(names)==true)
{
names.add(txtname.getText());
txtname.setText("");
}
else {
JOptionPane.showMessageDialog(null,"DUPLICATE! do not add");
}
}
});
public static boolean checkDuplicate(ArrayList<String> list) {
HashSet set = new HashSet();
for (int i = 0; i < list.size(); i++) {
boolean val = set.add(list.get(i));
if (val == false) {
return val;
}
}
return true;
}
It only says that I have duplicate when I already add it to the ArrayList and when I get the message I can't add anything else.
input example:
test
test
and then it stops accepting new Strings and only displays the message DUPLICATE! do not add
As I said in my comment:
This happens because you are basically creating a Set view of your ArrayList every time you call checkDuplicate rather than comparing the item you're trying to add with the existing list. In other words your checkDuplicate is written such that it only returns true when a duplicate already exists within the list. You need to compare the new item with the list instead. Step through your logic carefully either with a debugger or by manually writing down the values of your variables and you will see the problem.
You could simply change this line:
if(checkDuplicate(names)==true)
to this:
if(!names.contains(txtname.getText()))
You don't really need checkDuplicate since it's "reinventing the wheel" so to speak. ArrayList already provides a contains method that you can use to your advantage.
public boolean isConnectedTo(Suspect aSuspect){
boolean flag = false;
Registry tempRegistry = new Registry();
ArrayList<Communication> TempComms = new ArrayList<Communication>(tempRegistry.GetComms());
for(Communication comms : TempComms) {
System.out.println("here");
for(String PhoneNums : phoneNumbers){
if(PhoneNums.equals(comms.GetTransmitter())) {
for(String numbers : aSuspect.getNumbersList()) {
if(numbers.equals(comms.GetReceiver()))
flag = true;
}
}
}
}
return flag;
}
So I am trying to create a program that among other things, it will search two ArrayLists(TempComs and phoneNumbers) and it will return true or false whether a string in the first is the same with a string in the second or not. I create the new ArrayList TempComms with the method tempRegistry.GetComms(). GetComms() is a method in another class, (class Registry) and has just a return communications; command, communications is an ArrayList in the class Registry.(The ArrayList phoneNumbers is an arrayList of the class the code is into.) So normally with with
ArrayList<Communication> TempComms = new ArrayList<Communication>(tempRegistry.GetComms());
the ArrayList TempComms must be the same with ArrayList communication that exists in the other class. But I figured out that for some reason the problem is in TempComms, because the first for is never running(For that reason I used System.out.println("here"); but it never printed). I searched and tried a lot to find the solution of this problem of my own, but I didn't manage to make some progress, so I would be grateful if someone who knows where's the problem or what I do wrong tell me about it. Thanks anyway.
You are creating a new instance of the Registry which contains a list (comms).
Registry tempRegistry = new Registry();
Then you are trying to get that comm list by calling tempRegistry.GetComms() .
Unless you are populating this communication list in the constructor Registry() (not only instantiating, you should add some entries as well),
that list will be empty when for loop is called.
(Because you are clearly NOT populating it after creating the instance tempRegistry and before calling the for loop.
ArrayList<Communication> TempComms = new ArrayList<Communication>(tempRegistry.GetComms());
for(Communication comms : TempComms) {
Therefore, the TempComms list is also an empty list. Which is why the inside code of the for loop is not executing.
I really didn't want to resort to asking, however I'm at a dead end. I'm trying to build an array of objects stored within a hashmap into a single array. I'm building a minecraft plugin, and I need to be able to do this in order to reset all players to their natural state. However, for whatever reason, I can't seem to actually parse the Spectator[] array into individual pieces.
The goal is simply to allow more than 1 person to spectate. Here's my code:
public class EagleEye extends JavaPlugin implements Listener{
public HashMap<Spectatee, Spectator[]> spec = new HashMap(Spectatee, Spectator[]);
public HashMap<Spectatee, Spectator[]> orinven = new HashMap<Spectatee, Spectator[]>;
public HashMap<Spectatee, Spectator[]> eeinven = new HashMap<Spectatee, Spectator[]>;
#Override
public void onEnable()
{
//TODO:Who knows.
}
#Override
public void onDisable()
{
//TODO:Spec off any players being spectated and spectating.
Spectator[] frickinhell = spec.get(key));
//Creates a master list of all spectators by uuid
for(Spectator spec : spec.get(Spectator.class))
{
master.add(spec);
}
for(Object spec : master.toArray())
{
//Verify the player is online
if(Bukkit.getPlayer(master)
{
//Verify the player is still spectating
if(tators.get(uuid) == true)
{
//Stop spectating
tators.put(uuid, false);
}
}
}
}
I understand that much of this code is broken. However, my main concern is taking Spectator[] stored within all instances of Spectators[] stored within the hashmap and resetting their values to their defaults. Once I can access each individual instance of each object itself, I can reset their respective values using setters.
Cheers.
In spec.get(Spectator.class), Spectator.class doesn't match the type of your key, which is Spectatee. Therefore, it returns null.
You should pass an instance of Spectatee to spec.get() if you want to have a chance of getting a non-null value.
If you want to collect all the Spectators regardless of their key, you can iterate over the values of the Map :
for (Spectator[] value : spec.values())
for(Spectator spec : value)
{
master.add(spec);
}
I'm getting a very strange action in my code. I have an ArrayList of the following class.
class mySocket
{
public String name;
public Socket sck;
public mySocket(String n,Socket s)
{
this.name=n;
this.sck=s;
}
}
I declare the object like this
ArrayList<mySocket> handler = new ArrayList<>();
Now the problem is that when I try to remove an item using this method:
public void removeByName(String name)
{
synchronized(this)
{
mySocket t;
int i;
for(i=0;i<handler.size();i++)
{
t=handler.get(i);
if((t.name.equals(name)))
{
handler.remove(i);
break;
}
}
}
}
The remove function clears everything that follows the index.
For Example:
if this ArrayList has 3 elements and I call handler.remove(1) it removes not only 1 but also the object on line 2.
I think your issue is that you are using an indexed for loop and removing by index. In your example, if your list has 3 elements and you remove index 1, the object that was at index 2 is still there. It's just now at index 1.
A better way to do what you're attempting is to use an iterator or for-each loop.
//code outside for loop the same
for( mySocket socket : handler ) {
if((socket.name.equals(name)))
{
handler.remove(socket);
break;
}
}
Is the ordering of your mySocket objects important? If not, storing them in a Map keyed by name would save you some trouble. Then you would just call handler.remove(name). This operation is safe, even if name doesn't exist in the map. Also, for current uses of the collection handler that don't care aobut the name, you can retrieve the unordered Set of mySockets by calling map.values(). You would then be able to iterate over that Set using an iterator or for-each as above.
You CAN NOT remove items in a Collection while looping through them, the result, as you have seen, is undefined.
You either have to build a list of items to be removed and use
originalList.removeAll(itemsToBeRemoved);
Or you build your loop using an iterator.
Iterator<mySocket> handlerIterator = handler.iterator();
while (handlerIterator.hasNext()) {
mySocket t = handlerIterator.next();
if (t.name.equals(name)) {
handlerIterator.remove();
}
}