Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I have an a ChoiceBox that lists months values, when the user choose a value, it execute this lambda expression:
private TableView<IncomeFX> tableIncome;
private ChoiceBox<Month> choiceBoxIncomeMonths;
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
incomesData.addAll(temp);
};
return months;
}
and how i add the listener:
choiceBoxIncomeMonths.getSelectionModel().selectedItemProperty().addListener(setChoiceBoxIncomeMonthsBehaviour());
when I click on the choicebox, i get:
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:386)
at java.util.AbstractList$Itr.next(AbstractList.java:355)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:99)
at lite.money.ui.MainUI.lambda$1(MainUI.java:160)
at lite.money.ui.MainUI$$Lambda$120/1680764266.changed(Unknown Source)
it indicate that the problem is in the line where I call: addAll(temp)
how can i solve this ??? thanks
Since you haven't posted all the code, I'm going to guess you are running code on another thread that is trying to interact with the JavaFX data. When another thread tries to do this, it will throw an exception since only the JavaFX thread should be interacting with the data.
I can't really offer any more advice because I don't have the full codebase of what you are doing to truly say "yes at line X you are having thread Y access location X when it should not be."
Are you adding this on another thread perhaps? You will know the application better than I would since I don't have anymore code to go off of.
here is how i solve it, it's a bad code i know, but i don't know any other solution, i have to clear it twice or the items will be added like if i didn't clear it, if you do have an other solution i will be happy:
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
if (!lastMonthValuesFired) {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
ObservableList<IncomeFX> temp2 = FXCollections.observableList(new ArrayList<IncomeFX>());
for (IncomeFX t : temp) {
temp2.add(t);
}
incomesData.clear();
incomesData.addAll(temp2);
}
};
return months;
}
I had the same problem and did some research, this is the solution that I found that worked for me:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Java Program to demonstrate how to deal with
* ConcurrentModificationException.
* Unlike the name suggests, this error can come even if only
* one thread is modifying the collection e.g. List.
* It happens when you modify collection
* while iterating over it e.g. adding new element or removing elements.
*
* If you want to remove elements while traversing list then
* make sure you use Iterator's remove() method or not ArrayList's remove()
* method() to avoid ConcurrentModificationExcetpion.
*
* #author WINDOWS 8
*
*/
public class ConcurrentModExceptionDemo{
public static void main(String args[]) {
List<String> listOfPhones = new ArrayList<String>(Arrays.asList(
"iPhone 6S", "iPhone 6", "iPhone 5", "Samsung Galaxy 4",
"Lumia Nokia"));
System.out.println("list of phones: " + listOfPhones);
// Iterating and removing objects from list
// This is wrong way, will throw ConcurrentModificationException
for(String phone : listOfPhones){
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // will throw exception
}
}
// The Right way, iterating elements using Iterator's remove() method
for(Iterator<String> itr = listOfPhones.iterator();
itr.hasNext();){
String phone = itr.next();
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // wrong again
itr.remove(); // right call
}
}
System.out.println("list after removal: " + listOfPhones);
}
}
Source
Related
This question already has answers here:
java.lang.UnsupportedOperationException for removing a row from the javafx tableview
(2 answers)
Closed 4 months ago.
I don't understand why this method wont work because it worked literally three days ago. Whenever I try to use the method(press the button), The database operations work fine but the program throws an error whenever I try to remove from the actual table view so that the user wont see that row anymore. I added a filtered list to the initialize method and i am concerned that might be the cause of the problem. Here is my code:
Initialize Method:
private void initialize()
{
ObservableList<BloomClient> clients = FXCollections.observableArrayList();
firstNames.setCellValueFactory(new PropertyValueFactory<>("FirstName"));
lastNames.setCellValueFactory(new PropertyValueFactory<>("LastName"));
phoneNumbers.setCellValueFactory(new PropertyValueFactory<>("PhoneNumber"));
birthdays.setCellValueFactory(new PropertyValueFactory<>("Birthday"));
startDates.setCellValueFactory(new PropertyValueFactory<>("StartDate"));
endDates.setCellValueFactory(new PropertyValueFactory<>("ExpireDate"));
try {
clients = dBconnect.getClientList();
} catch (Exception e) {
e.printStackTrace();
}
FilteredList<BloomClient> filteredList = new FilteredList<BloomClient>(clients,b -> true);
filteredSearch.textProperty().addListener(((observable, oldValue, newValue) ->
filteredList.setPredicate(person ->
{
if(newValue == null || newValue.isEmpty())
return true;//nothing in text field
String lowerCaseFilter = newValue.toLowerCase();
if (person.getFirstName().toLowerCase().contains(lowerCaseFilter))
return true;//check first name
else if (person.getLastName().toLowerCase().contains(lowerCaseFilter))
return true;//check last name
else
return false;
})
));
SortedList<BloomClient> sortedList = new SortedList<>(filteredList);
sortedList.comparatorProperty().bind(clientList.comparatorProperty());
clientList.setItems(sortedList);
}
public void freezeAccount() throws SQLException, ParseException {
BloomClient person = clientList.getSelectionModel().getSelectedItem();
dBconnect.sendToFreeze(person);//this works
dBconnect.deleteClient(person);//this works
clientList.getItems().remove(person);//java.lang.UnsupportedOperationException
clientList.refresh();
}
Well, it's just a guess. But it's possible that the clientList is a List<> type that was created using Collections.unmodifiableList(). When you try to modify one of those, an UnsupportedOperationException is thrown.
public static List unmodifiableList(List<? extends T> list)
Returns an unmodifiable view of the specified list. This method allows
modules to provide users with "read-only" access to internal lists.
Query operations on the returned list "read through" to the specified
list, and attempts to modify the returned list, whether direct or via
its iterator, result in an UnsupportedOperationException.
See: https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableList-java.util.List-
Figured it out in a way but would like a deeper explanation. I ended up instead of deleting from the clientList(TableView) I deleted directly from the clients(ObservableList) and made that variable global to be reached by other methods. I'm not sure of the reasoning behind the initial problem.
BloomClient person = clientList.getSelectionModel().getSelectedItem();
dBconnect.deleteClient(person);
clients.remove(person);
clientList.refresh();
}
So I am having trouble trying to wrap my head around this coding problem: Here are four questions that they want me to answer:
How many times will 'getValue(…)' execute with the following inputs, and what will be the result?
(1) getValue("foo", 0);
(2) getValue("bar", 2);
(3) getValue("baz", 0);
(4) getValue("fubar", 1);
I know the first two answers:
1) will execute one time and return 1
2) will execute 1 time and return 3
But the last two problems (3,4) I don't understand. Can anyone help clarify what exactly this code is doing and hint to what the answers are?
Here is the code:
import java.util.HashMap;
import java.util.Map;
public class myClass {
private Map<String,Integer> map;
public myClass() {
map = new HashMap<>();
map.put("foo", 1);
map.put("bar", 3);
}
public int getValue(String input, int numRetries) throws Exception {
try {
return map.get(input);
}
catch (Exception e) {
if (numRetries > 3) {
throw e;
}
return getValue(input, numRetries + 1);
}
}
Thank you in advance.
The code as you rightly answered in (1) and (2) attempts to get a value from a HashMap given it's key.
The getValue() function is a recursive function, meaning it calls itself a number of times based on the 'numRetries' value
(3) the codes calls itself 4 times (where the numRetries progress from 0,1,2,3 before the '>3' clause becomes true and an Exception gets thrown)
(4) the codes calls itself 3 times (where the numRetries progress from 1,2,3 before the '>3' clause becomes true and an Exception gets thrown)
this is my first question on here and I did a search before forming it, so I hope everything is as required.
I am working on a school assignment in Java. I am able to produce the required output but there are a lot of null instances created first. I don't understand why. Information about the library the professor created for the course and the code are below
Library included with this course: i2c.jar. It can be found here.
included in this Library are the classes Country and CountryDB. The API for the Country class can be found at http://130.63.94.24/~roumani/book/doc/i2c/ca/roumani/i2c/Country.html
The API for the CountryDB class can be found at http://130.63.94.24/~roumani/book/doc/i2c/ca/roumani/i2c/CountryDB.html
I am asked to create a class called Game, using the Country and CountryDB APIs.
The only attribute is db, which is an instance of CountryDB.
The constructor only sets the attribute (db) for this instance to a new CountryDB object.
The class is also meant to include a method (called qa) that follows this pseudocode:
get a reference to the database's capital city list
determine the size of this list. Cal it n.
generate a random number in [0,n) called index.
invoke get(index) on the list to get a random capital city. Call it c
get a reference to the database's data map
invoke get(c) on the map to get a reference to a country. Call it ref.
The method is then supposed to return one of two Strings (which will be clear in the code). Everything works as it should, except I get a lot of "nulls" before the desired output. When made into a List, db has size 241 so I suspect I am creating 241 null instances and 1 proper instance. I have no idea why though. I have tested every line of code in my method and the constructor was dictated by the textbook.
CODE
package ca.yorku.eecs.caps;
import java.util.List;
import java.util.Map;
import ca.roumani.i2c.Country;
import ca.roumani.i2c.CountryDB;
public class Game
{
private CountryDB db;
public Game()
{
this.db = new CountryDB();
}
public String qa()
{
List<String> capitals = db.getCapitals();
System.out.println(capitals.toString());
int n = capitals.size();
System.out.println(n);
int index = ((int) (n * Math.random()));
System.out.println(index);
String c = capitals.get(index);
System.out.println(c);
Map<String, Country> data = db.getData();
Country ref = data.get(c);
if (Math.random() > 0.5)
{
return "What is the capital of " + ref.getName() + "? \n" + ref.getCapital();
}
else
{
return ref.getCapital() + " is the capital of? \n" + ref.getName();
}
}
public static void main(String[] args)
{
Game g = new Game();
System.out.println(g.qa());
}
}
the System.out.println() statements are only there to test when the nulls occur. It clearly happens immediately because my psvm output is 241 nulls (on separate lines) followed by my desired output. Can somebody please tell me what I am doing wrong?
And, more generally (to help more people) how do you implement classes, the constructor of which instantiates another class and sets it as an attribute value?
I appreciate any help. Also, please note, I am not trying to get others to do my work for me. I've spent hours on this and my lab TA also wasn't sure why it happens either. He would have helped me correct it had he known how.
Thank you.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I am keeping Node objects in a TreeSet:
public TreeSet<Node> viewNodes = new TreeSet<Node>();
Node looks like this:
public class Node implements Comparable<Node>{
private long nodeID;
...
public long getID() {
return nodeID;
}
#Override
public int compareTo(Node n) {
System.out.println("comparing: " +this + " with " + n + " -- " + new Long(nodeID).compareTo(n.getID()));
return new Long(nodeID).compareTo(n.getID());
}
#Override
public boolean equals(Object o){
if(o instanceof Node){
System.out.println((compareTo((Node)o) == 0));
return compareTo((Node)o) == 0;
}
return false;
}
#Override
public int hashCode(){
return new Long(nodeID).hashCode();
}
}
However, when I try to remove nodes, they do not get removed, and the TreeSet thinks they are not in the set!!
Remove code:
System.out.println("removing " + node);
System.out.println("viewNodes: " + viewNodes);
System.out.println("contains node?: " + viewNodes.contains(node));
viewNodes.remove(node);
System.out.println("now viewNodes looks like: " +viewNodes);
Output:
removing 5
viewNodes: [5, 4, 3, 2, 1]
comparing: 5 with 2 -- 1
comparing: 5 with 1 -- 1
contains node?: false
comparing: 5 with 2 -- 1
comparing: 5 with 1 -- 1
now viewNodes looks like: [5, 4, 3, 2, 1]
Why is this? I've implemented Comparable, shouldn't that be it?
As Andy figured out, your problem was that you changed the ID of your elements after insertion.
When using any kind of Set, you should take care not to change the elements while they are in the Set. From the Set interface documentation:
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.
The same thing applies to Map keys, and you will find an equivalent statement in the Map interface documentation.
In TreeSet(and the underlying TreeMap that it uses) the result from the compareTo method is used to place and then later find the elements. If the results of compareTo has changed between insertion and lookup, it will probably not work as it should.
I was changing the value of ID after inserting it into the TreeSet, just as Andy suggested. I imagine this caused the node to get sorted incorrectly.
It works now, thank you!
I have a list which is used to monitor arrival of certain entities in a strictly ascending numeric sequence and want to display an entry where there is an apparent break in the sequence.
Is there any way to highlight an entry in GlazeLists?
It's difficult to be certain about whether you're asking about how to highlight new elements within a list, or literally highlight a row in a UI component backed by a GlazedLists EventList.
For now I'll assume the former but feel free to clarify.
There is the notion of ListEvents within the GlazedLists package that allows one to get a small peak into changes that affect a list. It's not something I've played with much, and it seems rather rudimentary, but it's possible to use this mechanism given the right circumstances.
Here's a sample class which has a BasicEventList containing some integers. I've created a ListEventListener and attached it to the EventList. The ListEvents tell you where the element was inserted. It also contains a reference to the eventlist, so it's possible to get the newly inserted value, and also the value of the element preceding it. I do a quick comparison to see whether they're out of sequence.
Of course there are some major caveats here. The event handling is asynchronous, so it's entirely possible that the underlying list will changed considerably between the time of the original trigger and the time at which the listener is processing the event. In my sample it's ok because I'm only using append operations. Also I'm only using a BasicEventList; if it were a SortedList then the items would be inserted in different indexes, so the method I use for getting the current and previous values would be extremely unreliable. (There may be ways around this but I haven't applied myself to this problem in all honesty.)
At the very least you can use the listener to at least alert you to a list change and have another method outside of the listener class perform a scan of your list to determine whether there are items out of order.
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
public class GlazedListListen {
private final EventList<Integer> numbers = new BasicEventList<Integer>();
public GlazedListListen() {
numbers.addListEventListener(new MyEventListListener());
numbers.addAll(GlazedLists.eventListOf(1,2,4,5,7,8));
}
class MyEventListListener implements ListEventListener<Integer> {
#Override
public void listChanged(ListEvent<Integer> le) {
while (le.next()) {
if (le.getType() == ListEvent.INSERT) {
final int startIndex = le.getBlockStartIndex();
if (startIndex == 0) continue; // Inserted at head of list - nothing to compare with to move on.
final Integer previousValue = le.getSourceList().get(startIndex-1);
final Integer newValue = le.getSourceList().get(startIndex);
System.out.println("INSERTING " + newValue + " at " + startIndex);
if ((newValue - previousValue) > 1) {
System.out.println("VALUE OUT OF SEQUENCE! " + newValue + " # " + startIndex);
}
}
}
}
}
public static void main(String[] args) {
new GlazedListListen();
}
}
Note: I've only tested against GlazedLists v1.8.