I have an ArrayList with lots of objects. I want to be able to add any objects into a choice of 3 different LinkedLists. A user input will select which item to add to which LinkedList by typing the index they wish to be added. This is the kind of thing i'm after, but i just can't get it to work:
public void addToRepository(int indx, int r) {
if (r == 1){ //checks to see if chosen repository 1
for (int i=0; i < itemList.size(); i++) {
i = indx;
} // ignore this it was just me playing around to see if i'd be able to get the index this way..
repo1.add(itemList.get(indx)); //adds item from "itemList" with the index that
the user input has given
//other if statements
}
}
I'm not sure this is the correct idea but it gives error "Item cannot be converted to String". If not, how can i go about doing this?
So you have
ArrayList<Item> itemList = new ArrayList<Item>();
and you are trying to do -
repo1.add(itemList.get(indx));
As per the Exception you are getting it looks like repo1 has String data. You can do one of the following things -
Use repo1.add(itemList.get(indx).toString()); OR
Change repo1 generics to include Item data instead of String
Related
Is it possible to add a wildcard to a string in a list in Java?
I have a string, which has different endings (for example: Key(1), Key(2), Key(3), Key(4), Key(5) etc etc.)
Is it possible to somehow add a string to a list, with a wildcard, so I could just do something like:
list.add("Key*wildcard*");
And it would have all the different endings of the string?
Many thanks :-)
EDIT:
This is how I'll use it.
I'm coding something for a game, which has to check for a specific item. This item has charges, which defines the ending of the name of the item. The item is called "Games Necklace".
Now, I want to check, if the user has the item, and if not, it will buy one. I have a list of items required to do a certain task, but the Games Necklace changes name (from 8-1, so it can be either "Games Necklace(8), Games Necklace(7), Games Necklace(6) and down to 1). I want to check if the users has all the items in the list of items needed, but it should return true, if the user has any version of the necklace
You can add a wildcard string to the list, but then you have to implement the search in the list yourself, and you can't rely on contains to work for you, as it simply calls the equals method, and equals would not do what you need.
Here is a possible solution:
Instead of using a List, use a List, and define the item as a regular expression.
List<Pattern> requiredList = new List<>();
requiredList.add(Pattern.compile("Sword");
requiredList.add(Pattern.compile("Games Necklace\\(\\d+\\)");
Write a method that matches all the patterns in the list against another collection. e.g.
public static hasAll( List<Pattern> required, Collection<String> available) {
for ( Pattern pat : available ) {
boolean matched = false;
for ( String item : needed ) {
if ( pat.matcher(item).matches() ) {
matched = true;
break;
}
}
if ( ! matched ) {
return false;
}
}
return true;
}
Another option is to define your game items in their own class, not as strings. That class will have a "type" and a "display name". And you'll check it in the list using the type, which will be "Games Necklace" (for all of them), and display using the display name.
No, as it doesn't make sense for a String to have multiple values (in Java at least). You could do it by making a class that represents your "multi-string" (of course change the mechanics oif it to fit your exact needs.
class MultiString {
List<String> strings = new ArrayList<String>();
public MultiString(String, prefix, int numValues) {
for(int i = 0; i < numValues; i++) strings.add(prefix + String.valueOf(i));
}
public String get(int i) {
return strings.get(i);
}
}
Or you could just add several values to the list.
public void addStrings(List<String> list, String prefix, int numValues) {
for(int i = 0; i < numValues; i++) list.add(prefix + String.valueOf(i));
}
More specific solutions can't be given until we know your exact needs.
List<String> list = new ArrayList<>();
for (int i= 8; i>0;i--){
list.add("Games Necklace("+i+")");
}
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 an ArrayList of Items and I want to be able remove one Item from the list by entering only one Item attribute, for example its number (int ItemNumber). I also wanna do the same when I check Item quantities.
These are my equals() & contains() methods, do I need to make any changes here?
public boolean contains(T anEntry) {
boolean found = false;
for (int index = 0; !found && (index < numberOfEntries); index++) {
if (anEntry.equals(list[index]))
found = true;
}//end for
return found;
} // end contains
public boolean equals(Object object){
Item item = (Item) object;
if (itemNo == item.itemNo)
return true;
return false;
}
If you change the class Item equals() and compareTo() methods, so that they check only one object field, such as a quantity, it could result in strange behavior in other parts of your application. For example, two items with different itemNo, itemName, and itemPrice, but with the same quantities could be considered equal. Besides, you wouldn't be able to change the comparison attribute without changing the equals() code every time.
Also, creating a custom contains() method makes no sense, since it belongs to the ArrayList class, and not to Item.
If you can use Java 8, a clean way to do it is to use the new Collection's removeIf method:
Suppose you have an Item class with the num and name properties:
class Item {
final int num;
final String name;
Item(int num, String name) {
this.num = num;
this.name = name;
}
}
Given a List<Item> called items and an int variable called number, representing the number of the item you want to remove, you could simply do:
items.removeIf(item -> item.num == number);
If you are unable to use Java 8, you can achieve this by using custom comparators, binary search, and dummy objects.
You can create a custom comparator for each attribute you need to look for. The comparator for num would look like this:
class ItemNumComparator implements Comparator<Item> {
#Override
public int compare(Item a, Item b) {
return (a.num < b.num) ? -1 : ((a.num == b.num) ? 0 : 1);
}
}
Then you can use the comparator to sort and search for the desired elements in your list:
public static void main(String[] args) {
List<Item> items = new ArrayList<>();
items.add(new Item(2, "ball"));
items.add(new Item(5, "cow"));
items.add(new Item(3, "gum"));
Comparator<Item> itemNumComparator = new ItemNumComparator();
Collections.sort(items, itemNumComparator);
// Pass a dummy object containing only the relevant attribute to be searched
int index = Collections.binarySearch(items, new Item(5, ""), itemNumComparator);
Item removedItem = null;
// binarySearch will return -1 if it does not find the element.
if (index > -1) {
// This will remove the element, Item(5, "cow") in this case, from the list
removedItem = items.remove(index);
}
System.out.println(removedItem);
}
To search for another field like name, for example, you would need to create a name comparator and use it to sort and run the binary search on your list.
Note this solution has some drawbacks though. Unless you are completely sure that the list didn't change since the last sort, you must re-sort it before running the binarySearch() method. Otherwise, it may not be able to find the correct element. Sorting complexity is O(nlogn), so running it multiple times can get quite expensive depending on the size of your list.
Do you want to remove an object at a specific index? I'm not entirely sure what you mean by 'number field'. If so, jump to method: remove(int):
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove%28int%29
EDIT: If you want to find/adjust a field of an object in the Array list, you can do this (piece of my own code):
public boolean studentHasISBN(ArrayList<Student> st, String s){
for(Student j : st) {
if(s.equals(j.getRentedBookISBN()))
return true;
}
return false;
}
All you have to do is iterate through the list, and search through the field that you want to find. Then use the remove(int) method.
simply use the remove function of ArrayLists in Java:
theNameOfYourArrayList.remove(ItemNumber);
to remove the element which has the index (int ItemNumber)
to check if the element with item number (int ItemNumber) exists in your ArrayList (hypothetically called theNameOfYourArrayList):
theNameOfYourArrayList.get(ItemNumber);
I'm going to assume that by 'number field' you mean that you invoked ArrayList with the Integer data type. I have a few different solutions to your problem:
ArrayLists, assuming that the ArrayList is ArrayList<Integer> numList = new ArrayList<Integer>(); you can simply write a method that will search 'numList' and delete the index that the number is. The problem is, contains and find in ArrayLists can be slow.
public void deleteNumField(int field) {
// this will stop any error if field isn't actually in numList
// and it will remove the first index of field in the ArrayList
if(numList.contains(field)) numList.remove(numList.find(field));
}
HashSets, HashSets are a handy data type that is like an ArrayList, except, its data is its 'index' (sortof). I won't go in depth about how they work, but I will say that searching in them is considered O(1). This will make your deletion really easy, and fast. Note: the HashSet assumes there are no duplicate numbers, if there are use a HashMap.
HashSet<Integer> numList = new HashSet<Integer>();
public void deleteNumField(int field) {
// this will stop errors from attempting to remove a
// non-existant element, and remove it if it exists.
if(numList.contains(field)) numList.remove(field);
}
For more information on HashMaps, HashSets and ArrayLists, see:
http://docs.oracle.com/javase/8/docs/api/
I have my method which sorts all the movies in the array (dArray) of class dvd. now i need to sort available movies (setAvailable == true) ONLY. the array is dynamically filled in by customers entering movies from the menu. my code currently searches through the array and sorts all movies from A to B but now i want it to search and sort only the movies whereby d.setAvailable(true)... Thanks for your help. much appreciated
here is the sorted list of all the movies in the array:
if(e.getSource() == sortMovBtn)
{
if(dArray[0]==null)
{
JOptionPane.showMessageDialog(null,"No movies, please enter\na movie from the main menu","Error",JOptionPane.ERROR_MESSAGE);
}
else
{
BtnPanel.setVisible(false);
imgPnl.setVisible(false);
btnBackDvd.setVisible(true);
txtAreaSortDvd.setVisible(true);
sortDvdPnl.setVisible(true);
Dvd tmp;
for (int i = 0; i < manyDvd; i++)
{
for (int j = 0; j < (manyDvd - 1 - i); j++)
{
if (dArray[j].getTitle().compareTo(dArray[j+1].getTitle()) > 0)
{
tmp = dArray[j];
dArray[j] = dArray[j+1];
dArray[j+1] = tmp;
}
}
}
a = "";
for (int k = 0; k <manyDvd /*dArray.length*/; k++)
a += (dArray[k]);
txtAreaSortDvd.setText(a);
txtAreaSortDvd.setVisible(true);
txtAreaSortDvd.setEditable(false);
//Set font of text area
txtAreaSortDvd.setFont(new Font("Arial", Font.BOLD, 12));
//Initialize JScrollPane
JScrollPane pane1 = new JScrollPane(txtAreaSortDvd);
//Enable user to use wheel on mouse to scroll
pane1.setWheelScrollingEnabled(true);
//Set the scrollbar to always show
pane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//Add ScrollPane to Panel
sortDvdPnl.add(pane1);
//Add panel to frame
add(sortDvdPnl);
}
}
First, you shouldn't have code to work with your model (data) mixed in with UI code.
Second, you should not be sorting the data on the UI thread. Do the work on a background worker thread.
Third, you should not be coding up the sort yourself, especially not like that. Your sort is O(n^2). There are good options for sorting in java.util.Arrays for arrays or java.util.Collections for the collection classes.
There are two basic ways to go about sorting just the items that meet a certain criterion. You could sort the entire data set with a custom Comparator, matching first by the criterion and second by the rest of your sort criteria. Then your results would be at the start of the data, and you would only show the results until the first item that does not meet the criterion.
This has the advantage that it uses no extra space beyond what is already required to store your data.
A cleaner way would be to make a copy of just that portion of the data that meets the criterion, and then sort that. It would also be much easier to work with if the data was in a List instead of an array, since you would not need make two passes over the data: one to find out how many items match the criterion, and one to filter out the matching items. (In between, you would allocate an array to hold them.)
Suppose your data was in a List. You could get the available movies like this:
public List<Movie> getAvailable(List<Movie> movies) {
List<Movie> avail = new ArrayList<Movie>();
for (Movie movie : movies) {
if (movie.isAvailable()) {
avail.add(movie);
}
}
return avail;
}
You could then sort these movies (in their natural sort order) like this:
List<Movie> availOnly = getAvailable(movies);
Collections.sort(availOnly);
P.S. In Java 8 you will be able to do something like:
Iterable<Movie> avail = movies.filter(Movie::isAvailable).sorted();
use comparator http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html
I have a list of values. I want to remove the list item when check box is unclicked:
ArrayList<SalesRoutes> routeList = new ArrayList<SalesRoutes>();
ArrayList<String> selectedRoutes = new ArrayList<String>();
routeList =getSalesRoute();
for (int i = 0; i < routeList.size(); i++) {
CheckBox ch = new CheckBox(this);
ch.setId(i);
ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
if(arg0.isChecked()){
Log.i("add", routeList.get(arg0.getId()).getRouteCode());
selectedRoutes.add(routeList.get(arg0.getId()).getRouteCode());
System.out.println("----add ----" + selectedRoutes);
}else {
selectedRoutes.remove(arg0.getId());
Log.i("remove", routeList.get(arg0.getId()).getRouteCode());
System.out.println("----remove ----" + selectedRoutes);
}
}
});
}
Here I got IndexOutOfBoundsException because selectedRoutes is selected CheckBox values
selectedRoutes
[R0002]
routeList displays a list of routes on the screen. It fetches the route from a db.
Example routeList:
Route List
R0001
R0002 // selected this one ID is 1
R0003
calling remove from selectedRoutes(1).
selectedRoutes.remove(arg0.getId());
Here selectedRoutes only contains one record, which means there is no index 1.
How can I remove this?
The problem is with this section of code:
selectedRoutes.remove(arg0.getId());
Log.i("remove", routeList.get(arg0.getId()).getRouteCode());
System.out.println("----remove ----" + selectedRoutes);
You're hinging that on the (usually incorrect) assumption that the index of your route in your list of potential routes is the same as the index of your route in the list of selected routes. Instead, you'll want to get the route code of the route in your potential list of routes at that index, then iterate through your list of selected routes (which are actually just Strings containing route codes), and remove the index where the two match up. Code would look something like this:
String routeCode = routeList.get(arg0.getId()).getRouteCode();
index = -1;
for(int i = 0; i < selectedRoutes.size(); i++) {
if(routeCode.equals(selectedRoutes.get(i)) {
index = i;
break;
}
}
if(index > -1)
selectedRoutes.remove(index);
Log.i("remove", routeCode);
System.out.println("----remove ----" + selectedRoutes);
It would be much easier if you created selectedRoutes to be a collection of the same objects ArrayList<SalesRoutes> selectedRoutes. Since both collections would contain the references to the same object you could remove the object by its reference:
salectedRoutes.remove(routeList.get(arg0.getId()));
Calling ArrayList.remove(int location) will remove the object at that location in the array. It does not remove a object by it's Id value.
It appears you are adding an object to the arraylist at an index position returned by .getRouteCode()
But then you are trying to remove an object at an index position returned by .getId().
The two don't sync up.
You have mixed ArrayList.remove(int index) and ArrayList.remove(Object o).