I am trying to use the libgdx List widget to make a list of all the items in an arraylist. Well, actually my arraylist is a list of objects, and each of the objects contains a string that is the objects "name".
However, when I try to show these with a List, it lists them horizontally, not vertically. If I try to show the contents of a normal array it lists the contents vertically. I am implementing Screen in my classes.
For example,
ArrayList<String> PartyListEntries = new ArrayList<>();
private List PartyList = new List(skin);
PartyListEntries.add("ham");
PartyListEntries.add("hag");
PartyListEntries.add("ham");
PartyList.setItems(PartyListEntries);
table.setFillParent(true);
table.top().left().padTop(10).padLeft(10);
table.add(PartyList);
stage.addActor(table);
This shows: [ham, hag, ham]
But if I make a String array and have the array contents be { "ham", "hag", "ham" }
then it shows
[ham]
[hag]
[ham]
horizontally(without the line breaks).
This is my first issue with list. My 2nd issue is that when string values are the same, it selects both of them. In the 2nd example, if I set the default selection to index zero it will put both index 0 [ham] and index 2 [ham] as selected. It will do this for every string that has the same value as whatever is selected. I.. don't want it to do this. I want them to be treated as unique since they are.
I am trying to look at the code for List but to be honest it's kind of beyond me. I don't know what causes these problems. I could really try to figure it out and I might and it will take me a long time, but I figure maybe you guys already know what is causing this. Or maybe can just offer me a good alternative to List.
Thanks!
Regarding the first question: the Libgdx widget just uses the toString method of whatever object you give it to make the text label. So that's why you get different results with lists and String arrays. It was just the preference of whomever wrote each of those classes how to format the array to a String. If you want to use the List class, you could subclass it and change the toString method to the way you want it, or you could create a List wrapper class that does its own method of converting the list to a String.
Regarding the second question: This is a peculiarity of Java. If you hard code strings (put them in your actual code in a class with quotation marks), then the compiler makes all matching strings into a single shared instance of the String class. So "ham" and "ham" are the same instance of String, the same object.
You can get around this by wrapping your string with a String constructor like this. new String("ham"). This will force it to create a separate instance of String.
Example:
String s0 = "a";
String s1 = "a";
String s2 = new String("a");
boolean b0 = s0.equals(s1); //evaluates true
boolean b1 = s0.equals(s2); //evaluates true
boolean b2 = s0==s1; //evaluates true
boolean b3 = s0==s2; //evaluates false
If you load your strings in from a file at runtime, matching strings will be different instances.
Related
I need to check a List of Strings to contain certain predefined strings and - in case all these predefined string are contained into the list - I need to write the list to a File.
As a first approach I thought to do something like
if(doesTheListContainPredefinedStrings(list))
writeListIntoFile(list);
Where the doesTheListContainPredefinedStrings and writeListIntoFile executes loops to check for the prefefinedStrings and to write every element of the list to a file, respectively.
But - since in this case I have to worry about performance - I wanted to leverage the fact that in the doesTheListContainPredefinedStrings method I'm still evaluating the elements of the list once.
I also thought about something like
String[] predefinedStrings = {...};
...
PrintWriter pw = new FileWriter("fileName");
int predefinedStringsFound = 0;
for (String string : list)
{
if (predefinedStrings.contains(string))
predefinedStringsFound++;
pw.println(string);
}
if (predefinedStringsFound == predefinedStrings.length)
pw.close();
Since I observed that - at least on the system where I'm developing (Ubuntu 19.04) - if I don't close the stream the strings aren't written to the file.
Nevertheless, this solution seems really bad and the file would still be created, so - if the list wouldn't pass the check - I'd have the problem to delete it (which requires another access to the storage) anyway.
Someone could suggest me a better/the best approach to this and explain why it is better/the best to me?
check the reverse case — is any string from predefs in the strings-to-check-list missing?
Collection<String> predefs; // Your certain predefined strings
List<String> list; // Your list of strings to check
if( ! predefs.parallelStream().anyMatch( s -> ! list.contains( s ) ) )
writeListIntoFile(list);
The above lambda expression stops as soon as the first string from predefs can't be found in the strings-to-check-list and returns true — You must not write the file in this case.
It does not check if any additional strings are in the strings-to-check-list, that are not contained in the predefs strings.
I'm trying to add 1 to an integer in a 2-dimensional ArrayList.
I'm using the set() method with the element + 1 as the second argument, but the "+ 1" isn't working. When I retrieve the element, it defines it as an object, not an integer. How do I get around this?
Code:
ArrayList<ArrayList> inventoryList = new ArrayList(
Arrays.asList(new ArrayList<String>(), new ArrayList<Integer>()));
...
(inventoryList.get(1)).set(i, ((inventoryList.get(1)).get(i) + 1));
Error:
Main.java:47: error: bad operand types for binary operator '+'
(inventoryList.get(1)).set(i, ((inventoryList.get(1)).get(i) + 1));
^
My code is at this ideone page. This code is translated from python and I'm currently debugging it so don't worry about the other errors.
ArrayList<ArrayList> inventoryList = ...
You are using the raw variant of ArrayList for your inner lists, such an ArrayList indeed contains Objects instead of Integers. You shouldn't use those raw ArrayLists and instead use generic ones:
What is a raw type and why shouldn't we use it?
Looking at your code a bit more, it seems that inventoryList is supposed to contain two lists, one that contains the items you have (as strings) and one that contains how many you have (as integers) where you can find how many you have of the item at index i in the first list by looking in the second list at that same index i.
If that is correct there are multiple ways to fix this, indeed, casting the Objects to Integers works, but then you are still using raw types, which you probably shouldn't. To fix this you should just not keep the ArrayList<String> and the ArrayList<Integer> in the same list. You could just have:
ArrayList<String> inventoryItems = ...
ArrayList<Integer> inventoryItemCounts = ...
separately (you don't need a list if it always contains exactly 2 items, a list of strings and a list of integers). However a cleaner solution would be, as was suggested in the comments by user2418306, to use a map
Map<String, Integer> inventory = ...
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html, that way each string (item) in your inventory has exactly one corresponding integer (number you have of that item) and you don't have to get that by using the "at the same index" trick.
Looking at you code a bit though, I would say that more is going wrong with the inventory. You print your inventory using:
for (int i = 0; i < inventoryList.size(); i++){
System.out.println((inventoryList.get(1)).get(i) + " : " + (inventoryList.get(0)).get(i));
}
and you iterate through it in that way in other places as well. However, if i'm not misunderstanding anything, inventoryList.size() is always going to be 2 (the inventoryList contains 2 lists, one of strings and one of integer). To get the number of distinct items (strings) in your inventory you'd have to do inventoryList.get(0).size() (or inventoryList.get(1).size() because that is going to be the same). However, things will get easier if you chose a better datatype for your inventory. I would look into the mentioned Map. Using that, you easily get the correct number using inventory.size().
You can solve your problem by casting to Integer
inventoryList.get(1).set(i, (Integer) inventoryList.get(1).get(i)+1);
Of course first take a look on comments below your question to see how to properly init your list, so you wont need explicit cast.
The way it is declared, your lists are list of Object. You need to cast the result from second get() with (Integer), like:
inventoryList.get(1).set(i, (Integer)inventoryList.get(1).get(i)+1);
Note: There are unneeded ().
My program produces a list of Strings in one activity, then passes it to another activity, and the second activity uses the strings.
When I test by printing out each element of the list at the beginning of the second activity, the printout looks perfect. For example, if I am hoping for the list to contain "Lemon Juice", it prints out exactly right, but yet the logic in the second activity still doesn't work. If I add "Lemon Juice" just like that to the list manually, the logic in the second activity works fine, so the issue is that somehow the string in the received List is not really "Lemon Juice". But:
It prints out exactly correctly (including checking for spaces in front and at the end).
I have tried explicitly casting the received list elements as (String) just to be sure they are Strings.
If I run "Lemon Juice".contains(received String) it comes back true, and if I run received String.contains("Lemon Juice") it
comes back true, but if I run received String.equals("Lemon Juice") it comes back false. This is very confusing to me.
Can anyone think of a possible explanation for how something that is cast as a string, prints as a string, and looks like a string, is not performing like a string?
EDIT to include some code as requested:
// instance variable at top of class--list to which strings will be added for use in
// 2nd activity
private List<String> exs = new ArrayList<String>();
// get array of strings from extra from intent from first activity
String[] recExs = getIntent().getStringArrayExtra(BrowseActivity.EXS);
for (int exx = 0; exx < recExs.length; exx++) {
String curEx = (String) recExs[exx];
exs.add(curEx);
}
Somehow, when I pass exs to the method I need to use the strings, it doesn't work, even though, as explained above, printing and calling contains etc all show that the string, before I added it to exs, was at I wanted it to be.
It's hard to help when you only posted a small snippet of your code.
But I'm guessing the reason String.contains works but String.equals doesn't is that maybe there is space in the Strings. Try String.trim on both side of the Activity when passing and receiving data.
I've been reading up on it, but every question I've found has asked for slightly different things, such as only wanting a single letter for their array, or in a different language (I'm new and only learning java at the moment), so here I am.
I want to set up an array that uses the user's input for their names.
What I have so far is this, I'm assuming this is the declaration line, where later I use an input line to define a value within the array (which I also am unsure how to do)
String[] array = {"name"};
But I don't know how to for example print.out the object or keep up with which name will be what value. I appreciate your time taken to teach me!
EDIT for further clarification. I'm trying to write up a small app that asks the user for numerous names, addresses, and phone numbers (Type name -> Type name's address -> type name's phone number, ask if they want to add another person, if yes then go back to asking for another name)
I am unsure how to set up a String array or how to use it throughout. However, thanks to your input and coming back after some fresh air, I have a better idea how to word it for google. Thank you guys for your help, even if it was just to gesture a better articulated question.
An array is a sequence of values. You have created an array of Strings that is one String long. To access the value at a specific of an array, use array subscript notation: the name of the array followed by a pair of square brackets ([]) with the index in between them.
String[] anArrayOfStrings = {"string0", "string1", "string2"};
anArrayOfStrings[0]; //the first element
System.out.println(anArrayOfStrings[1]); //print the second element
anArrayOfStrings[2] = "new string value"; //assign the third element to a new value
if (anArrayOfStrings[0].equals("string0") //evaluate the first element and call a method
{
//this block will execute anArrayOfStrings[0] is "string0"
}
anArrayOfStrings[3]; //error, index out of bounds
Simply declaring the array would be
String[] names;
In your code you both declare and assign it in the same line by using an initializer list.
To assign individual elements, use the [] notation. Note that once you initialized you list to be only one String long, it cannot become longer than without be re-assigned. To declare an array of any size, you can use:
String[] arrayWithInitialSize = new String[5]; //holds five strings, each null to begin with
I have a combobox which stores "Computer ,Code:21","History ,Code:31" and also the number of items can be changed.but when I write this code for getting its items:
List<String> bIHELessons = new ArrayList<String>();
for (int i=0;i<jComboBox1.getItemCount();i++) {
String lessons = (String) jComboBox1.getItemAt(i);
if (lessons != null&& lessons.trim().length()!=0) {
bIHELessons.add(lessons);
System.out.println(bIHELessons.toString());
}
}
it will show these sentences in the console:
[Computer,Code=21]
[Computer,Code=21, History,Code:31]
Because you are appending to the list with bIHELessons.add(..). Each subsequent call adds on to the already printed string.
If you want to still add to the ArrayList and print the current item that is in the ArrayList, then use System.out.println(bIHELessons.get(i)); rather than using what you are now. I also don't think you need to use toString() because your objects are already in the type string.
Change System.out.println(bIHELessons.toString()); to System.out.println(lessons); if you only want to print the string you are currently iterating on.
From what I can see your code is doing what it should be doing. Are you wanting to know why you are seeing all items repeated with each additional call to the print screen?
That is happening because the toString() method of the List is putting all the items in the list into a single string.
I don't think the problem is with JComboBox but rather with your expectations. System.out.println(bIHELessons.toString()); will print out the entire contents of the bIHELessons ArrayList. Since you're adding a new String to the ArrayList on each iteration, it's logical that your System.out.println(bIHELessons.toString()); would show a progressive accumulation of content.
Your question isn't clear but you may consider moving the System.out.println outside of your loop and determining if that's what you're looking for.
You are printing out the ToString() representation of your entire list. If you want to print out the object you could just print out the lessons variable instead.