I want to have a collection of items. Let’s call it the stock
I want GUI that contains two buttons: one adds more items to a JComboBox
from the stock, another removes items from the combo and replenishes the stock with them
I need the first iterator to take notice of any additions made by the second one (the one that moves items from the combo back to the stock). Obviously, no ConcurrentModificationException
s
It seems I need a collection that returns a “strongly-consistent” Iterator
(or whatever it’s called). I considered ConcurrentLinkedDeque
, but its Iterator
is explicitly documented as weakly-consistent
// ConcurrentLinkedDeque
/**
* Returns an iterator over the elements in this deque in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
* <p>The returned iterator is
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*
* @return an iterator over the elements in this deque in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();
}
they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.
java.util.concurrent doc
So how should I do it? Here’s my attempt. I couldn’t break it, i.e. make it “lose” an item due to the aforementioned weak consistency, but I guess it’s because I needed to create a ton of threads and orchestrate some sort of race. Let’s just believe the documentation that it’s not a reliable approach
package demos.combo;
import javax.swing.*;
import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ComboBoxDemo {
private static final Deque<Plant> plantStock = plantStock();
private static JButton addButton;
private static JButton removeButton;
public static void main(String[] args) {
JFrame frame = new JFrame("Searchable Combo Box Demo");
JPanel mainPanel = new JPanel();
JComboBox<Plant> combo = new JComboBox<>();
combo.addItemListener(ComboBoxDemo::onItemSelection);
initialComboBoxItems().forEach(combo::addItem);
addButton = createAddItemButton(combo);
removeButton = createRemoveItemButton(combo);
mainPanel.add(addButton);
mainPanel.add(removeButton);
mainPanel.add(combo);
frame.setContentPane(mainPanel);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static ArrayList<Plant> initialComboBoxItems() {
ArrayList<Plant> items = new ArrayList<>();
items.add(new Plant("Potato"));
items.add(new Plant("Peach"));
items.add(new Plant("Banana"));
items.add(new Plant("Orange"));
items.add(new Plant("Carrot"));
items.add(new Plant("Cabbage"));
return items;
}
private static Deque<Plant> plantStock() {
Deque<Plant> extraPlants = new ConcurrentLinkedDeque<>();
extraPlants.add(new Plant("Rose"));
extraPlants.add(new Plant("Cactus"));
extraPlants.add(new Plant("Quinoa"));
extraPlants.add(new Plant("Oak"));
extraPlants.add(new Plant("Cacao"));
return extraPlants;
}
private static JButton createAddItemButton(JComboBox<Plant> comboBox) {
JButton addButton = new JButton("Add item");
addButton.addActionListener(e -> {
Optional<Plant> optionalPlant = Optional.ofNullable(plantStock.poll());
optionalPlant.ifPresent(comboBox::addItem);
addButton.setEnabled(!plantStock.isEmpty());
removeButton.setEnabled(true);
});
return addButton;
}
private static JButton createRemoveItemButton(JComboBox<Plant> comboBox) {
JButton removeButton = new JButton("Remove item");
removeButton.addActionListener(e -> {
Plant firstItem = comboBox.getItemAt(0);
comboBox.removeItem(firstItem);
plantStock.add(firstItem);
removeButton.setEnabled(comboBox.getItemCount() > 0);
addButton.setEnabled(true);
});
return removeButton;
}
private static void onItemSelection(ItemEvent event) {
if (event.getStateChange() != ItemEvent.SELECTED) return;
Plant selectedItem = (Plant) event.getItem();
System.out.printf("Selected item: " + selectedItem + "n");
}
}
Wacage is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.