java arraylist.add overwrites with last value - java

have this class
public class ObjetoOS {
private ArrayList<String> atribute = new ArrayList<String>();
public ObjetoOS (String a){
atribute.add(a);
}
public ObjetoOS (ArrayList<String> a){
atribute = a;
}
which i use like this
public class TablaSimbolica {
private static ArrayList<ObjetoOS> tableOS = null;
public static void addAtributos(ArrayList<String> newOnes){
if (tableOS == null){
tableOS = new ArrayList<ObjetoOS>();
for (String s : newOnes){
ObjetoOS newObj = new ObjetoOS(s);
tableOS.add(newObj);
}
}
else{
ArrayList<ObjetoOS> aux = new ArrayList<ObjetoOS>();
for (ObjetoOS os : tableOS){
ArrayList<String> oldOnes = new ArrayList<String>();
oldOnes = os.getAtributo();
for (String s : newOnes){
oldOnes.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnes);
aux.add(newObj);
newObj = null;
oldOnes.remove(s);
}
}
tableOS = aux;
}
}
so basically: addAtributos checks if the array its empty. if it is it just adds the strings, if its not, i have to combine it with the new ones, like a cartisan product thing.
when adding new strings, although im creating a new array, and a new objectOS which y turn to null after adding it, the elements overwrite with the last one.
for example, if i had strings "true" "false", and i have to add "female" "male", the output is:
[TRUE, Female]
[TRUE, Male]
[TRUE, Male]
[TRUE]
[TRUE]
[FALSE, Female]
[TRUE]
[TRUE]
[FALSE, Male]
[FALSE, Male]
i cant figure out where im missing the point here. it gives me an error if i erase the static both from the ArrayList tablaOS or from the addAtributos method.
EDIT: solved! i changed the object class making a new empty constructor and a method adding a string array with a for.
the loop it ended up being
for (String s : newOnes){
oldOnes.add(s);
ObjetoOS nuevo = new ObjetoOS();
nuevo.addAtribute(oldOnes);
aux.add(nuevo);
oldOnes.remove(s);

Some of your problems lies here:
ArrayList<String> oldOnes= new ArrayList<String>(); // This line is pointless
oldOnes= os.getAtributo(); // oldOnes will be overwritten here
for (String s : newOnes)
{
oldOnes.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnes);
aux.add(newObj );
newObj = null;
oldOnes.remove(s);
}
When you here pass oldOnes to the ObjetoOS constructor, the newObj will have a reference to the same list as oldOnes, when you then later remove the element from oldOnes you also remove it from newObj's list(since they are the same).
The same does not happen if you use the String constructor because primitive datatypes, also including Strings, are copied (passed by value) when passed to a method.
There's a good explanation on how objects are passed in java here: Is Java "pass-by-reference" or "pass-by-value"?
Edit:
Also your tableOS will point to a new ArrayList<> every time you call your method, if I understand your solution correctly this might be more what you want:
...
for (ObjetoOS os : tableOS)
{
for (String s : newOnes)
{
ArrayList<String> oldOnesPlusNewOne = new ArrayList<>();
oldOnesPlusNewOne.addAll(os.getAtributo());
oldOnesPlusNewOne.add(s);
ObjetoOS newObj = new ObjetoOS(oldOnesPlusNewOne);
tableOS.add(newObj);
}
}

Might I suggest simplifying the code some? If your trying to add attributes to an array list, maybe create an attributes class instead. You can create a class for the atributos, give it some members etc... and easily change to and make the atributos a list to hold aritbutos. I'd suggest the class be name Atributo. Your trying to do to much in one class. Single responsibility is key. One class that defines the atributo and one to store a list of them. This should fix your problem and uncomplicate your code. Now you can only store 10 members to the array list without specifying the amount of elements you want it to hold. If you don't it will only hold the default of 10 and the last element will be over written.
import java.util.ArrayList;
public class Atributos
{
// attributes list
ArrayList<String> atributos = new ArrayList<String>();
// add string to attributes list
public void addAtributos(String atributo)
{
atributos.add(atributo);
}
// add list of strings to attribute list
public void addAtributos(ArrayList<String> atributo)
{
for(String attr : atributo)
{
atributos.add(attr);
}
}
}

Related

Check if an arrayList contains an array

I have an arrayList that contains arrays. How do I check if the arrayList contains a specified array? I used .contains method and it returns false instead of expected true.
import java.util.ArrayList;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
action.add(new String[]{"appple", "ball"});
String[] items = new String[]{"appple", "ball"};
if (action.contains(new String[]{"appple", "ball"})) {
System.out.println("Yes");
}
System.out.println(action.contains(items)); // False
}
}
As you are creating different arrays (even if the contents are the same), contains will result false.
However, if you do this:
List<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"apple","ball"};
action.add(items);
if (action.contains(items))
System.out.println("Yes");
This will print Yes.
Also, some examples of the behaviour:
String[] items = new String[]{"apple","ball"};
action.add(items);
String[] clone = items.clone();
String[] mirror = items;
action.contains(clone); // false
action.contains(mirror); // true
items[0]="horse";
System.out.println(mirror[0]); // "horse"
System.out.println(clone[0]); // "apple"
System.out.println(action.get(0)[0]); // "horse"
mirror[1]="crazy";
System.out.println(clone[1]); // "ball"
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
clone[1]="yolo";
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
System.out.println(mirror[1]); // "crazy"
System.out.println(action.get(0).hashCode()); //2018699554
System.out.println(items.hashCode()); //2018699554
System.out.println(clone.hashCode()); //1311053135
System.out.println(mirror.hashCode()); //2018699554
Custom "contains"
The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values.
As a workaround, you could implement your own contains method. Something like:
If you wish to get the index:
static int indexOfArray(List<String[]> list, String[] twin)
{
for (int i=0;i<list.size();i++)
if (Arrays.equals(list.get(i),twin))
return i;
return -1;
}
And then, call it like:
String[] toSearch = new String[]{"apple","ball"};
int index = indexOfArray(action, toSearch);
if (index>0)
System.out.println("Array found at index "+index);
else
System.out.println("Array not found");
If the index is bigger than -1, you can get your original array by just:
String[] myArray = action.get(index);
HashMap + identifier
An alternative would be storing the arrays into a HashMap by declaring an identifier for each array. For example:
Base64 ID
This will give the same result for the same values, as the encoded value is based on the entries, not the Object's reference.
static String getIdentifier(String[] array)
{
String all="";
for (String s : array)
all+=s;
return Base64.getEncoder().encodeToString(all.getBytes());
}
And then you could:
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"}; // *[1234]
action.add(items);
arrayMap.put(getIdentifier(items), items); // id = QUJDYWFh
//....
//Directly finding the twin will fail
String[] toSearch = new String[]{"apple","pear", "banana"}; // *[1556]
System.out.println(action.contains(toSearch)); // false
//But if we get the identifier based on the values
String arrId = getIdentifier(toSearch); // id = QUJDYWFh
System.out.println(action.contains(arrayMap.get(arrId))); //true
//arrayMap.get(arrId)-> *[1234]
//.....
Name.
Choose a representative name and use it as Id
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"};
action.add(items);
arrayMap.put("fruits", items);
//...
System.out.println(action.contains(arrayMap.get("fruits"))); // true
The 'contains' method compares equivalent hashCode values.
So if you make it like below*, it will pass.
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"appple","ball"};
action.add(items);
System.out.println("TO STRING");
System.out.println("--"+action.get(0));
System.out.println("--"+new String[]{"apple","ball"});
System.out.println("HASHCODES");
String[] sameValues = new String[]{"apple","ball"};
System.out.println("--"+action.get(0).hashCode());
System.out.println("--"+items.hashCode());
System.out.println("--"+sameValues.hashCode());
System.out.println("CONTAINS");
System.out.println("--"+action.contains(items)); // *this
System.out.println("--"+action.contains(sameValues));
System.out.println("--"+action.contains(new String[]{"apple","ball"}));
}
}
result is:
TO STRING
--[Ljava.lang.String;#7b1d7fff
--[Ljava.lang.String;#299a06ac
HASHCODES
--1243554231
--1243554231
--2548778887
CONTAINS
--true
--false
--false
Regarding the code shown when printing the array, these don't override toString(), so you get:
getClass().getName() + '#' + Integer.toHexString(hashCode())
For example:
[Ljava.lang.String;#7b1d7fff
[ stands for single dimension array
Ljava.lang.String stands for the type
#
7b1d7fff Hex representation of the hashcode
However, if you want to compare the values, there is the following method.
public class main {
public static void main(String[] args) {
String[] items = new String[]{"apple","ball"};
ArrayList<String> action = new ArrayList<>(Arrays.asList(items));
if (action.contains("apple")) {
System.out.println("Yes");
}
}
}
You can iterate over this list and for each element, i.e. array, call Arrays.equals method to check equality of arrays until first match, or till the end of the list if none match. In this case it can return true for each element:
List<String[]> list = List.of(
new String[]{"appple", "ball"},
new String[]{"appple", "ball"});
String[] act = new String[]{"appple", "ball"};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
This method internally calls String#equals method for each element of the array, i.e. String, so this code also returns true:
List<String[]> list = List.of(
new String[]{new String("appple"), new String("ball")},
new String[]{new String("appple"), new String("ball")});
String[] act = new String[]{new String("appple"), new String("ball")};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
According to JavaDocs, "contains" method is using "equals" and "hashCode" methods in order to check whether an object is contained.
A leading question:
Do you know what's the implementation of "equals" for arrays?
Check it and you will probably understand your code's execution result (hint: ==).
As "Hovercraft Full Of Eels" said, a better design will be using a list of some Collection which you DO understand / control it's "equals" and "hashCode" methods.

Get value from HashMap<String, ArrayList<String>>

[updated code] (Sorry guys, I didn't provide the whole code, because in my experience large codes seem to "scare off" possible helpers.)
For an ExpandableListView I want to build a HashMap<String, ArrayList<String>> where String is the name of a category and ArrayList<String> the names of animals belonging to that category. I populate the HashMap as such:
HashMap<String, ArrayList<String>> map_groups_childs;
ArrayList<String> list_group_titles;
private void prepareListData(ArrayList<Id_triv_cat> search_results) {
list_group_titles = new ArrayList<String>(); // this is a list of group titles
map_groups_childs = new HashMap<String, ArrayList<String>>(); // this is a map. each group title gets a list of its respective childs
// temporary List of items for a certain category/group
ArrayList<String> temp_childs_list = new ArrayList<String>();
// "search_results" is an ArrayList of self defined objects each containing an ID, a name and a category name
int count = search_results.size();
int i_cat = 0;
int i=0;
// if category "i" is the same as the next category "i+1", add child to list
for (i=0; i<count-1; i++) {
// build group with category name
list_group_titles.add(search_results.get(i).get_type());
// while category does not change, add child to the temporary childs-array
while (i<=count && search_results.get(i).get_type().equals(search_results.get(i+1).get_type())) {
temp_childs_list.add(search_results.get(i).get_name());
i++;
}
// must be done, as the while loop does not get to the last "i" of every category
temp_childs_list.add(search_results.get(i).get_name());
Log.i("DEBUG", temp_childs_list.size()); // --> returns always more than 0
Log.i("DEBUG", temp_childs_list.toString()); // --> returns always something like [word1, word2, word3, ...]
Log.i("DEBUG", list_group_titles.get(i_cat)); // --> returns always a single word like "Insekten"
// add [group_title:list_of_childs] to map
map_groups_childs.put(list_group_titles.get(i_cat++), temp_childs_list);
// clear temp_list, otherwise former category's species will be added to new category
temp_childs_list.clear();
}
Log.i("DEBUG", map_groups_childs.containsKey("Insekten")); // --> returns true
Log.i("DEBUG", map_groups_childs.size()); // --> returns 10
Log.i("DEBUG", map_groups_childs.get("Insekten").size()); // --> returns 0
Log.i("DEBUG", map_groups_childs.toString()); // --> returns {Insekten=[], Reptilien=[], ...}
}
The use of the same i in the for- and while-loop may seem wrong or confusing, but it is okay. No i is skipped in any way or used twice.
All keys I put in the HashMap are there, but the ArrayList I want to get with (for example) map_groups_childs.get("Insekten") is empty. What am I doing wrong?
...
map_groups_childs.put(..., temp_childs_list);
temp_childs_list.clear();
}
Objects are passed as a reference in Java. You are always putting the same List in to the Map and clearing it after every iteration. Thus every value in the Map points to the same List which is empty.
What you probably need is something like this:
for( ... ) {
List<String> tempChildsList = new ArrayList<>();
...
mapGroupChilds.put(..., tempChildsList);
}
Thus a new List is created on every iteration.
I also agree with #CandiedOrange your code is a mess and probably overly complex. In general the point of abstractions like List and Map is to not access things by counting numerical indexes all the time.
Note that in Java, the convention is that identifiers for variables are camelCase, not under_scored.
Near as I can tell what you need are the 5 lines in the second group below
HashMap<String, ArrayList<String>> map_groups_childs = new HashMap<String, ArrayList<String>>();
ArrayList<String> list_group_titles = new ArrayList<String>();
ArrayList<String> temp_childs_list = new ArrayList<String>();
list_group_titles.add("insects");
temp_childs_list.add("Swallowtail");
temp_childs_list.add("Small White");
temp_childs_list.add("Large White");
temp_childs_list.add("Silverfish");
int k = 0;
Log.i("DEBUG", list_group_titles.get(k)); // --> returns "insects"
Log.i("DEBUG", temp_childs_list); // --> returns [Swallowtail, Small White, Large White, Silverfish]
map_groups_childs.put(list_group_titles.get(k), temp_childs_list);
Log.i("DEBUG", map_groups_childs.size()); // --> returns 1 not 10
Log.i("DEBUG", map_groups_childs.containsKey("insects")); // --> returns true
Log.i("DEBUG", map_groups_childs.get("insects").size()); // --> returns 4 not 0
Even with the edit, your code is still missing huge clues about what is going on. I've made some guesses and if I'm right, you are making this way too hard.
I've inferred the existence of a class Id_triv_cat that has getters named get_name() and get_type().
static class Id_triv_cat {
String type;
String name;
Id_triv_cat( String type, String name )
{
this.name = name;
this.type = type;
}
public String get_type()
{
return type;
}
public String get_name()
{
return name;
}
}
I've also written this code to test your prepareListData() method.
public static void main(String[] args){
ArrayList<Id_triv_cat> search_results = new ArrayList<Id_triv_cat>();
search_results.add( new Id_triv_cat("type1", "name1") );
search_results.add( new Id_triv_cat("type2", "name2") );
search_results.add( new Id_triv_cat("Insekten", "insekten name1") );
search_results.add( new Id_triv_cat("Insekten", "insekten name2") );
search_results.add( new Id_triv_cat("type3", "name3") );
new Test().myPrepareListData( search_results );
}
And while I could fix your minor defect like a good SE denizen I'm going to risk having all of this migrated to Programmers because your biggest problem is a design problem. Your code is suffering from a lack of clear local identifiers. Instead of making locals you are having a dot fest with the java utility classes that's making your code pointlessly hard to follow.
If, as I suspect, you are trying to build a map from a list of Id_triv_cat's using their type as a key and name as a value then try this:
private void myPrepareListData(ArrayList<Id_triv_cat> search_results) {
// Each group title is mapped to a list of its respective children
HashMap<String, ArrayList<String>> my_map_groups_childs =
new HashMap<String, ArrayList<String>>();
for (Id_triv_cat search_result : search_results)
{
String type = search_result.get_type();
String name = search_result.get_name();
if ( my_map_groups_childs.containsKey(type) )
{
ArrayList<String> names = my_map_groups_childs.get(type);
names.add(name);
}
else
{
ArrayList<String> names = new ArrayList<String>();
names.add(name);
my_map_groups_childs.put(type, names);
}
}
Log.i("DEBUG", "my_map_groups_childs = " + my_map_groups_childs);
}
This displays: my_map_groups_childs = {Insekten=[insekten name1, insekten name2], type1=[name1], type3=[name3], type2=[name2]}
See how a few well chosen local's can make life so much easier?
If that's not what you wanted you're going to have to make your question clearer.
And Radiodef is right. You really should use camelCase when you code in Java.

Writing a method with ArrayList of strings as parameters

I am trying to write a method that takes an ArrayList of Strings as a parameter and that places a string of four asterisks in front of every string of length 4.
However, in my code, I am getting an error in the way I constructed my method.
Here is my mark length class
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
And the following is my main class:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
ish.marklength4(words);
}
}
Essentially in this case, it should run so it adds an arraylist with a string of "****" placed before every previous element of the array list because the lengths of the strings are all 4.
BTW
This consists of adding another element
I am not sure where I went wrong. Possibly in my for loop?
I got the following error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Marklength.marklength4(Marklength.java:7)
at MarklengthTestDrive.main(MarklengthTestDrive.java:18)
Thank you very much. Help is appreciated.
Let's think about this piece of code, and pretend like you don't get that exception:
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
Ok, so what happens if your list just contains item.
You hit the line if(n.length() ==4){, which is true because you are looking at item, so you go execute its block.
Next you hit the line themarklength.add("****");. Your list now has the element **** at the end of it.
The loop continues, and you get the next item in the list, which happens to be the one you just added, ****.
The next line you hit is if(n.length() ==4){. This is true, so you execute its block.
You go to the line themarklength.add("****");, and add **** to the end of the list.
Do we see a bad pattern here? Yes, yes we do.
The Java runtime environment also knows that this is bad, which is why it prevents something called Concurrent Modification. In your case, this means you cannot modify a list while you are iterating over it, which is what that for loop does.
My best guess as to what you are trying to do is something like this:
import java.util.ArrayList;
public class Marklength {
ArrayList<String> marklength4(ArrayList <String> themarklength){
ArrayList<String> markedStrings = new ArrayList<String>(themarklength.size());
for(String n : themarklength){
if(n.length() ==4){
markedStrings.add("****");
}
markedStrings.add(n);
}
System.out.println(themarklength);
return markedStrings;
}
}
And then:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
words = ish.marklength4(words);
}
}
This...
if(n.length() ==4){
themarklength.add("****");
}
Is simply trying to add "****" to the end of the list. This fails because the Iterator used by the for-each loop won't allow changes to occur to the underlying List while it's been iterated.
You could create a copy of the List first...
List<String> values = new ArrayList<String>(themarklength);
Or convert it to an array of String
String[] values = themarklength.toArray(new String[themarklength.size()]);
And uses these as you iteration points...
for (String value : values) {
Next, you need to be able to insert a new element into the ArrayList at a specific point. To do this, you will need to know the original index of the value you are working with...
if (value.length() == 4) {
int index = themarklength.indexOf(value);
And then add a new value at the required location...
themarklength.add(index, "****");
This will add the "****" at the index point, pushing all the other entries down
Updated
As has, correctly, been pointed out to me, the use of themarklength.indexOf(value) won't take into account the use case where the themarklength list contains two elements of the same value, which would return the wrong index.
I also wasn't focusing on performance as a major requirement for the providing a possible solution.
Updated...
As pointed out by JohnGarnder and AnthonyAccioly, you could use for-loop instead of a for-each which would allow you to dispense with the themarklength.indexOf(value)
This will remove the risk of duplicate values messing up the index location and improve the overall performance, as you don't need to create a second iterator...
// This assumes you're using the ArrayList as the copy...
for (int index = 0; index < themarklength.size(); index++) {
String value = themarklength.get(index);
if (value.length() == 4) {
themarklength.add(index, "****");
index++;
But which you use is up to you...
The problem is that in your method, you didn't modify each string in the arraylist, but only adds 4 stars to the list. So the correct way to do this is, you need to modify each element of the arraylist and replace the old string with the new one:
void marklength4(ArrayList<String> themarklength){
int index = 0;
for(String n : themarklength){
if(n.length() ==4){
n = "****" + n;
}
themarklength.set(index++, n);
}
System.out.println(themarklength);
}
If this is not what you want but you want to add a new string "**" before each element in the arraylist, then you can use listIterator method in the ArrayList to add new additional element before EACH string if the length is 4.
ListIterator<String> it = themarklength.listIterator();
while(it.hasNext()) {
String name = it.next();
if(name.length() == 4) {
it.previous();
it.add("****");
it.next();
}
}
The difference is: ListIterator allows you to modify the list when iterating through it and also allows you to go backward in the list.
I would use a ListIterator instead of a for each, listiterator.add likely do exactly what you want.
public void marklength4(List<String> themarklength){
final ListIterator<String> lit =
themarklength.listIterator(themarklength.size());
boolean shouldInsert = false;
while(lit.hasPrevious()) {
if (shouldInsert) {
lit.add("****");
lit.previous();
shouldInsert = false;
}
final String n = lit.previous();
shouldInsert = (n.length() == 4);
}
if (shouldInsert) {
lit.add("****");
}
}
Working example
Oh I remember this lovely error from the good old days. The problem is that your ArrayList isn't completely populated by the time the array element is to be accessed. Think of it, you create the object and then immediately start looping it. The object hence, has to populate itself with the values as the loop is going to be running.
The simple way to solve this is to pre-populate your ArrayList.
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>() {{
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
}};
}
}
Do tell me if that fixes it. You can also use a static initializer.
make temporary arraylist, modify this list and copy its content at the end to the original list
import java.util.ArrayList;
public class MarkLength {
void marklength4(ArrayList <String> themarklength){
ArrayList<String> temp = new ArrayList<String>();
for(String n : themarklength){
if(n.length() ==4){
temp.add(n);
temp.add("****");
}
}
themarklength.clear();
themarklength.addAll(temp);
System.out.println(themarklength);
}
}

How to keep adding values to a List using a JButton and JTextArea without them being re-written

private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
String newCD = (cdInput.getText());
List <String> cdList = new ArrayList();
Collections.addAll(cdList, "ExampleG","ExampleB","ExampleR","ExampleX");
cdList.add(""+newCD);
List<String> sorted = new ArrayList<String>(cdList);
Collections.sort(sorted);
bigBox.setText("");
bigBox.append("Original Order\n**************\n");
for (String o : cdList) {
bigBox.append(o);
bigBox.append("\n");
}
bigBox.append("\n\nSorted Order\n************\n");
for (String s : sorted) {
bigBox.append(s);
bigBox.append("\n");
}
}
With this code, I can add 1 value, but when I try to add another one, it erases the original and replaces it. What can I do to prevent this?
PS. I'm trying to make a List of CDs, and be able to add new ones and have them also sorted and put in thier original order
Based on your code, you have no centralised instance of List, which means, each time you activate the button, it has no concept of what was previously in the list.
Start by creating an instance variable of the cd List and only add new items to it as required.
Something more like...
private List<String> cdList = new ArrayList<>(25);
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
String newCD = (cdInput.getText());
cdList.add(newCD);
List<String> sorted = new ArrayList<String>(cdList);
Collections.sort(sorted);
bigBox.append("Original Order\n**************\n");
for (String o : cdList) {
bigBox.append(o);
bigBox.append("\n");
}
bigBox.append("\n\nSorted Order\n************\n");
for (String s : sorted) {
bigBox.append(s);
bigBox.append("\n");
}
}

Java:HashMap<String,String> storing same value as key and value.?

I am getting this strange output in HashMap.
I have two ArrayList<String> one containing the key and another containing value.
My HashMap<String,String> will store only string as key and value pair. But key itself is getting stored in value. I have checked my value arraylist, it's printing the value. But during putting it's setting it as key itself.
Code snippet is:
public HashMap<String,String> getLstBarring()
{
ArrayList<String> temparrLst=setPreParameters(fetchPreDetails, 1);
System.out.println("KEY" + temparrLst);
ArrayList<String> tempArrLstId=setPreParameters(fetchPreDetails, 14);
System.out.println("VALUE" +tempArrLstId);
int length=tempArrLstId.size();
for(int index=0;index<length;index++)
{
System.out.println("VALUE IN KEY" + temparrLst.get(index));
System.out.println("VALUE IN VALUE" + tempArrLstId.get(index));
this.lstBarring.put(temparrLst.get(index), tempArrLstId.get(index));
}
System.out.println("INSIDE ODB....>>>>>>>>>>>>>>" + lstBarring);
return this.lstBarring;
}
Problem is:
1st SOP is KEY-printing all the key correctly.
2nd SOP is VALUE-printing all the value correctly.
3rd SOP is VALUE IN KEY----printing all the values.
4th SOP is VALUE IN VALUE--printing all the values.
Hence after ever iteration I am getting value,value in HashMap whereas it should be key,value.
Here's look at my Method:-
public ArrayList<String> setPreParameters(HashMap<Integer,String> fetchPreDetails,int index)
{
switch(index)
{
case 1:
{
arrLstData.clear();
splittedString=fetchPreDetails.get(1).split(",");
Collections.addAll(arrLstData, splittedString);
break;
}
return arrLstData;
Please guide me as to where am I going wrong.
My guess is that either fetchPreDetails is a collection being mutated by setPreParameters() or else setPreParameters() is mutating some other shared state so that the collection referenced by your temparrLst is being changed on the second call to setPreParameters(). I.e.
List<String> strings = new ArrayList();
strings.add("a");
strings.add("b");
List<String> otherStrings = strings;
otherStrings.add("c");
I expect your code assumes that strings would contain "a" and "b" and that otherStrings would contain "a", "b", and "c". This isn't how object references work in Java. The line List<String> otherStrings = strings; makes both strings and otherStrings point to the same collection, and thus changes made using either name affect the same thing.
Edit: Your newly-posted code seems to prove my hypothesis. You have a variable called arrLstData that you clear, populate, and return on each call to setPreParameters(). You're returning the same collection every time you call this method. Therefore you just have multiple handles to the same collection instead of multiple collections. You need to create a new collection and return it each time you call setPreParameters().
Edit again: Maybe this will make it clearer. Here's what you're doing:
public static void main(String[] args) {
Foo f = new Foo();
List<String> list1 = f.getList("a", "b");
System.out.println(list1);
List<String> list2 = f.getList("c", "d");
System.out.println(list2);
System.out.println(list1);
}
static class Foo {
private List<String> myList = new ArrayList<String>();
public List<String> getList(String... strings) {
myList.clear();
myList.addAll(Arrays.asList(strings));
return myList;
}
}
Note that this exhibits exactly the behavior that you're describing, and the correct way to solve it is something like this:
public static void main(String[] args) {
Foo f = new Foo();
List<String> list1 = f.getList("a", "b");
System.out.println(list1);
List<String> list2 = f.getList("c", "d");
System.out.println(list2);
System.out.println(list1);
}
static class Foo {
public List<String> getList(String... strings) {
List<String> result = new ArrayList<String>();
result.addAll(Arrays.asList(strings));
return result;
}
}
You are reusing the same List over and over at your setPreParameters Method.
The List in arrLstData is returned and stored in temparrLst, now you are clearing the the Lists content, putting new stuff in it and storing it to tempArrLstId.
Now the three variables all contain the very same list (they are not equals, its the same!).
There is only one List object at the whole example!
Its like you got a box and label it "A" on one side put stuff in it, label it "B" on another side and wondering why the box "B" is empty when you turn box "A" upside-down.
Did you maybe mean something like this?
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GlobalsMess {
private Map<String, String> lstBarring = new HashMap<String, String>();
private Map<Integer, String> fetchPreDetails = new HashMap<Integer, String>();
public GlobalsMess() {
fetchPreDetails.put(1, "john,vikam,david");
fetchPreDetails.put(14, "1,2,3");
}
public Map<String, String> getLstBarring() {
List<String> tempKeys = setPreParameters(fetchPreDetails.get(1));
System.out.println("KEY" + tempKeys);
List<String> tempIds = setPreParameters(fetchPreDetails.get(14));
System.out.println("VALUE" + tempIds);
for (int index = 0; index < tempIds.size(); index++) {
System.out.println("VALUE IN KEY" + tempKeys.get(index));
System.out.println("VALUE IN VALUE" + tempIds.get(index));
this.lstBarring.put(tempKeys.get(index), tempIds.get(index));
}
System.out.println("INSIDE ODB....>>>>>>>>>>>>>>" + lstBarring);
return this.lstBarring;
}
public List<String> setPreParameters(String fetchPreDetailsValue) {
List<String> arrLstData = new ArrayList<String>();
Collections.addAll(arrLstData, fetchPreDetailsValue.split(","));
return arrLstData;
}
public static void main(String[] args) {
new GlobalsMess().getLstBarring();
}
}
Output:
KEY[john, vikam, david]
VALUE[1, 2, 3]
VALUE IN KEYjohn
VALUE IN VALUE1
VALUE IN KEYvikam
VALUE IN VALUE2
VALUE IN KEYdavid
VALUE IN VALUE3
INSIDE ODB....>>>>>>>>>>>>>>{david=3, vikam=2, john=1}

Categories

Resources