I am using a hashmap to populate a jtable. The user selects a row(s) and clicks a edit button. I am taking the value from the hashmap and placing it in a textarea. The user can make changes and then clicks another button. I have the new value and the key, but I am not sure how to write the changed value back to the right key in the hashmap.
THis is where I am writing the data out to the textarea
private void outputSelection() {
StringBuffer csb = new StringBuffer();
String s = "";
int[] row = selectTable.getSelectedRows();
for(int i = row.length-1; i >= 0; i--){
String check = (String) EdiMapTableModel.getMapInstance().getValueAt(i, EdiMapTableModel.getMapInstance().COMMENT_COL);
if (!isNullOrEmpty(check)) {
if (csb.length() > 0) {
csb.append("\n");
}
csb.append(check);
}
}
s = csb.toString();
csb.setLength(0);
output.append(s);
}
This is where I am trying to put the value back
private void inputSelection() {
String s = output.getText();
int[] row = selectTable.getSelectedRows();
for(int i = row.length-1; i >= 0; i--){
TCComponentItemRevision check = (TCComponentItemRevision) EdiMapTableModel.getMapInstance().getValueAt(i, EdiMapTableModel.getMapInstance().ITEMID_COL);
EdiMapTableModel.getMapInstance().commentBackMap(check, s);
repaint();
}
}
This is where I am trying to put it back in the map
public void commentBackMap(int row, TCComponentItemRevision id, String comment) {
if(model.containsKey(id)) {
model.put(id, comment);
}
fireTableDataChanged();
}// end commentBackMap()
I know containsKey is not right above. id is the key value
Do I need to iterate through the hashmap looking for a match? Don't know if it matters but it is a linkedhashmap instead of a hashmap
According to the HashMap#put documentation:
Associates the specified value with the specified key in this map. If
the map previously contained a mapping for the key, the old value is
replaced.
So all you have to do is call put with the same key and the new value, it will do the replacement for you.
This also applies to LinkedHashMap because it inherits the put method from HashMap.
If you want to maintain the location of your map entry, you can't put it again since that's going to move it to the end of the LinkedHashMap. You'll need a holder object, say an Object[1], where you'll replace its member without putting the map entry again.
Or maybe reevaluate your choice of LinkedHashMap.
Related
This question already has answers here:
Increment an Integer within a HashMap
(13 answers)
Closed 10 months ago.
I'm new to HashMaps, and I was wondering if there was a way to add values together if they have the same key.
For example, when I have the key 'a' and the value is 20 and later on I use the key 'a' again and the value is 10 the value should now be 30.
I don't know how I would check if the Value already is in the HashMap and then use the same value again. The adding part could be done with just a variable that copies the current value and adds the new one, I guess.
I am guessing you want a hashmap for character vs integer and want to add the integer to already present value in case the value is present.You can do something like below:
public hashMapImpl(char ch, int number){
Map<Character,Integer> map = new HashMap<>();
if(map.containsKey(ch)){
map.put(ch, map.get(ch)+number);
}
else{
map.put(ch,number);
}
}
Where ch will be your key and number will be something that you want to store at particular key.
you can use compute method to add/sum a value in case a key exists, or create a new entry in case it doesn't.
Map<String, Integer> map = new HashMap<>();
String myKey = "a";
Integer myValue = 10;
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
map.compute(myKey, (key, value) -> {
if (value == null)
return myValue;
else
return value + myValue;
}
);
System.out.println(map);
Outputs:
a={10}
a={20}
Of course, putting this compute logic inside a method will make you code cleaner :)
I will use an example class called HashMapExamle to explain this.
Inside the class I will create a HashMap called bigHashMap assuming that was your initial hashMap with prior data.
I also have a main method to call the method that will solve your problem. I have named the method bigHashMap. So for starters, i have initialized our prior HashMap named bigHashMap and initialized wit with some new key-value pairs.
I will printout the value of the HashMap. I will then add a value with the same key, in this case food with the value 15, by calling the hashMapValueAdd method I have created and passing the key(food) and value(15) to it.
The concept of the method is:
Check if the HashMap contains the key.
if it has it, it will get the value with that ky and add the new value to it. it will then replace the value at the key with the new value.
If the key is not found in the hashmap then the new key-value pair will just be inserted.
class HashMapExample {
private static HashMap<String, Integer> bigHashMap;
public static void main(String[] args) {
bigHashMap = new HashMap<>();
// Add test data
bigHashMap.put("food", 200);
bigHashMap.put("transport", 20);
bigHashMap.put("entertainment", 40);
System.out.println("Data before : \n" + bigHashMap);
hashmapValueAdd("food", 15);
System.out.println("Data after : \n" + bigHashMap);
}
private static void hashmapValueAdd(String key, int value) {
// Check if hashMap contains the given key
if (bigHashMap.containsKey(key)) {
// Get previous value with the same key
int valueWithSameKey = bigHashMap.get(key);
// Increment the value with incoming value
int newValue = valueWithSameKey + value;
// Put updated value into HashMap
// bigHashMap.put(key, +value);
bigHashMap.replace(key, newValue);
} else {
// Put the current key since it does not exist in the HashMap
bigHashMap.put(key, value);
}
}
}
I hope this solves your problem.
You can check out these HashMap explanations to get a better understanding.
Java HashMap - W3Schools
Java MAp - Jakob Jenkov
Java HashMap replace()
Update the Value Associated With a Key in a HashMap
I am reading through a CSV and saving the data to objects (an object is created for each row). The rows in the CSV are grouped by the first element (group number) - somewhere between 2-10ish rows share a group number. There are ~180 groups in the data set. To handle this data more easily, I store the data into HashMaps, where the key is the group number, and the value tied to the key is an ArrayList of the data objects.
As I iterate through the CSV's rows, I add objects to the HashMap, using the row's group number to tell where to put the new data object. If the object has a group number which has not been entered into the CSV yet, it creates a new key (its group number) and an ArrayList of data objects, containing just itself.
If the row's group number IS a key in the HashMap, it gets the ArrayList tied to the group number, adds the new data object to it, and uses the put function to re-add the new entry, with the updated ArrayList (now with one more data entry tied to the shared group number).
Code example:
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
HashMap<Integer,ArrayList<CSVData>> CSVDataMapNew = new HashMap<Integer,ArrayList<CSVData>>();
while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,")))
{
System.out.println(line);
String[] csvDataNew = line.split(",");
String currentGroup = csvDataNew[GroupIndex];
try {
currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
} catch (Exception ex) {
currentGroupNumber = previousGroupNumber;
}
String path = csvDataNew[PathIndex];
startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
endLine = Integer.parseInt(csvDataNew[EndLineIndex]);
CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);
if (CSVDataMapNew.containsKey(currentGroupNumber)) { //if it does contain the current key, add the current object to the ArrayList tied to it.
csvListNew = CSVDataMapNew.get(currentGroupNumber);
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
} else { //if it doesnt contain the current key, make new entry
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
System.out.println(CSVDataMapNew.size());
System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
}
csvListNew.clear(); //to make sure no excess objects are entered into the map.
previousGroupNumber = currentGroupNumber;
}
There are appropriate try-catches, etc. and the CSVDataTable is declared in its own class, being referenced statically.
The issue is, when I add in print statements at each step, its like each ArrayList within the HashMap gets erased at the end of every loop. So once the CSV is finished being iterated through, it has each key value, but the ArrayLists tied to each key are all empty. (Evidenced by looping through the HashMap afterwards).
How can I resolve this, so when I enter a value into the ArrayList and re 'put' the key and updated ArrayList into the Map, it keeps its data?
So once the CSV is finished being iterated through, it has each key
value, but the ArrayLists tied to each key are all empty. (
This
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
should be invoked and associated to each key of your map.
But you use a single instance of the ArrayList as value for every key of your map.
And at the end of your method, you do :
csvListNew.clear();
So all your values of your map are an empty ArrayList as all refers to the same ArrayList.
To solve your problem, if the key doesn't exist in the map you should create a new ArrayList and associate it to this key :
ArrayList<CSVData> csvListNew = CSVDataMapNew.get(currentGroupNumber);
if (csvListNew == null)
csvListNew = new ArrayList<CSVData>();
CSVDataMapNew.put(csvListNew);
}
Then reuse the csvListNew variable to add the element in:
csvListNew.add(clone);
It simplifies your actual code that has undesirable duplication.
You always put the same ArrayList instance as value in your HashMap. That's the ArrayList instance created before the loop and referenced by the csvListNew variable.
This means that when you call csvListNew.clear(), you clear all the ArrayLists of your HashMap.
This can be fixed by creating a new ArrayList each time you want to put a new entry in your HashMap:
if (CSVDataMapNew.containsKey(currentGroupNumber)) {
csvListNew = CSVDataMapNew.get(currentGroupNumber);
csvListNew.add(clone);
} else {
csvListNew = new ArrayList<>(); // that's the main required fix
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
System.out.println(CSVDataMapNew.size());
System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
}
In addition, remove the csvListNew.clear() call.
When you get a list from a hashMap you get a reference to the list. Everything you do with this list afterwards will affect the list that is in the map. This means two things:
You don't have to put the List back into the map after you added something to it
You have to create a new List for every Map entry. You currently don't do that.
This should fix it (also some adjusted code style):
Map<Integer,List<CSVData>> CSVDataMapNew = new HashMap<>();
while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,")))
{
System.out.println(line);
String[] csvDataNew = line.split(",");
String currentGroup = csvDataNew[GroupIndex];
try {
currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
} catch (Exception ex) {
currentGroupNumber = previousGroupNumber;
}
String path = csvDataNew[PathIndex];
startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
endLine = Integer.parseInt(csvDataNew[EndLineIndex]);
CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);
if (CSVDataMapNew.containsKey(currentGroupNumber)) {
CSVDataMapNew.get(currentGroupNumber).add(clone);
} else {
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
CSVDataMapNew.put(currentGroupNumber, csvListNew);
csvListNew.add(clone);
}
previousGroupNumber = currentGroupNumber;
}
I have an ArrayList which holds employee record details from data inputted into JTextFields. I have displayed this with a showMessageDialog box to confirm that they are being added to the list correctly.
The employees are created and added to the list correctly but how do I cycle through the ArrayList one record at a time and have the information displayed in the JTextFields?
Edited as below:
I don't think I have asked the question properly. I have a button that enables me to show the contents of the first element of my array list to the GUI. See below:
nField.setText(nameList.get(0).getName());
bField.setText(nameList.get(0).getBirth());
jField.setText(nameList.get(0).getID());
What I need is something to show the next element.
I have a list iterator that I am trying to use but I simply can’t get it to work.
I have tried this but it results in the last element being shown:
for (int i = 0; i < nameList.size(); i++) {
nameList.get(i);
nField.setText(nameList.get(i).getName());
bField.setText(nameList.get(i).getBirth());
jfield.setText(nameList.get(i).getID()); }
There are different options, but the short of it is, you'll have to tie your employee record to the JTextField somehow. One way to do this is by creating a simple object to hold the relation:
public class EmployeeRecordToJTextfield {
private EmployeeRecord employeeRecord;
private JTextField jTextField;
public EmployeeRecordToJTextfield(EmployeeRecord employeeRecord, JTextField jTextField) {
this.employeeRecord = employeeRecord;
this.jTextField = jTextField;
}
public EmployeeRecord getEmployeeRecord() {
return employeeRecord;
}
public JTextField getJTextField() {
return jTextField;
}
}
Instead of the EmployeeRecord, you stick instances of this class in the list:
List<EmployeeRecordToJTextfield> list = new ArrayList<>();
list.add(new EmployeeRecordToJTextfield(employeeRecord, jTextField));
When you iterate over this list, you can transfer the data you choose:
for (EmployeeRecordToJTextfield e : list) {
JTextField textField = e.getJTextField();
EmployeeRecord record = e.getEmployeeRecord();
textField.setText(record.getName());
}
Another option, maybe simpler, is by converting your list to a map and map EmployeeRecords to their JTextField.
Update based on the Question update
I hope I now understand what you're asking, but if so, I'd just do this:
Store the index of the 'current' shown item in a variable or hidden GUI field.
private int currentIndex = 0; // Start with the first item.
When you want to show the next item (perhaps through a Next or Previous button), get the next value. Compensate for list length:
int nextIndex = currentIndex+1;
if (nextIndex >= nameList.size()) nextIndex = 0;
if (nextIndex < 0) nextIndex = nameList.size()-1;
Now you can use nextIndex to fetch the correct entry from your list:
nField.setText(nameList.get(nextIndex).getName());
bField.setText(nameList.get(nextIndex).getBirth());
jfield.setText(nameList.get(nextIndex).getID());
And don't forget to update the currentIndex:
this.currentIndex = nextIndex;
Use for loop:
for(JTextField a : your_list){
do_something();
}
I have a JSP that has a list of DVDs and want to send list of the selected (checkboxes) to a second page for processing. In the second page I have used :
String selected[] = request.getParameterValues("checkboxGroup");
to get the list of selected checkboxes. I would like to get either the key OR value (bse I am building a table) of the selected index. eg; if the user selected the first checkbox, -> I want to be able to access either Pirates or 299.
I converted a 2d array into a map as below thinking that if I am able to get the index of the map I would be able to access either the key or value as below:
String [ ][ ] myArray = {
{"Pirates", "299"},
{"Travellers", "145"},
{"Zoopy", "89"},
{"Farewell", "67"},
{"Junies", "98"},
{"WakUp", "55"},
{"Space", "100"},
{"Solar", "199"},
{"Strom", "200"},
{"Wind", "200"}
};
final Map<String, String> map = new HashMap<String, String>(myArray.length);
for (String[] mapping : myArray) {
map.put(mapping[0], mapping[1]);
}
I am however stuck and don't know where to go from here and would appreciate suggestions from those more experienced.
Maps don't have indexes, so you'll have to abandon that idea.
You need to use an indexed data structure, such as a List or an array. Perhaps a List of custom objects, containing the string and integer values would be appropriate?
The Key-/Value-/Entry-Sets of a map are (as you notice) sets, that means unordered lists. So you actually can parse them to lists with indexes, however the index of lements wont be consistent.
Finally..This is what I used instead;
TreeMap dvdstree = new TreeMap();
// Add some dvds.
dvdstree.put("Pirates", 5);dvdstree.put("Solar",124);
dvdstree.put("Travellers",145);dvdstree.put("Zoopy", 89);
dvdstree.put("Farewell", 67);
//Get a set of the entries
Set set = dvdstree.entrySet();
// Get an iterator
Iterator iterator = set.iterator();
//Used a count keep track of iteration -> compare with name of checkbox
int count = 0;
//Printing into html table
out.print("<table>");
//Gets the selected checkboxes from previous page
String selected[] = request.getParameterValues("checkboxGroup");
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
//used a count to keep a track of where I am in the List
count++;
for(int i=0; i<selected.length; i++){
if(count == Integer.parseInt(selected[i])){
out.print("<tr><td>"+ me.getKey()+ "<td>"+me.getValue()+"<td/></tr>");
//Used this to get value of checkbox so that I could perform arithmetic in my class
String value= (me.getValue()).toString();
double valueDouble = Double.parseDouble(value);
myBean.addPrice(test2);
}
}
}
out.print("<tr><td>Total</td><td>"+myBean.getTotal()+"</td>");
out.print("</table>");
The method below (generateID())it generate a random ids, And when i store students in the HashMap i want to check if the generated id is not exist in the hashMap value and if its exists I want to generate a new id and then store it, The problem with the method store sometimes it does not store all the student because some student might have the same id and this is not allowed, So what is the best why to check that all ids are uniqe and if there is duplication the method generateid will be called again util all the ids are uniqe and then it will store it, I want to ensure that the ids values produced by generateId() are all different
private String generateId(String perfix, int numberaOfDigits)
{
for(int i=0;i<numberaOfDigits;i++)
{
perfix += randomGenerator.nextInt(9)+ 1;
}
return perfix;
}
public void store(Student student)
{
int index = 0;
studentMap.setId(generateId("AB-",1));
while(index <= studentMap.size())
{
for(Student stu : studentMap.values() )
{
if(student.getStduentID().equals(stu.getStduentID()))
{
student.setId(generateId("AB-",1));
}
}
index++;
}
}
studentMap.put(student.getStduentID(),student);
}
you can use the containsKey() method to check if an ID is already in use as key
Use an UUID. Or a sequence as already answered
If that's actually a Map implementation, you should be able to use .containsKey(). The problem is that, depending on how well written your ID generator is, this can cause significant performance issues over time. Say you have a 6 digit ID, and in a few years 80000 students have passed through the system. How many guesses will it need before it finds one of the remaining 20000 available keys?
You can get from the map with the generated Id, if it returns null, then it doesn't exist
yet.
Map<Long, Object> myMap = new HashMap<Long, Object>();
Long id = generateRandomId()
Object value = getMyObjectValue();
while(myMap.get(id) != null){
id = generateRandomId();
}
myMap.put(id, value);
I would eliminate the generateId() method altogether, and simply do this:
private int id;
then:
student.setId(id++);
I suggest to try following implementation to get unique random number each time.
Add items to the list .
Use Collections.shuffle(list); to shuffle the list .
Iterate over list and get random number each time from the given range. (For below case range is from 0 to numberOfStudent-1).
int numberOfStudent = 10;
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < numberOfStudent; i++)
list.add(i);
Collections.shuffle(list);