I'm trying to delete an item from an array list by selecting it from a JList and clicking "Delete".
The code I have so far,
buttondeleteContact.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (contactList.getSelectedIndex() != -1) {
people.removeElementAt(contactList.getSelectedIndex());
People.remove(contactList.getSelectedIndex());
System.out.println(People);
}
});
I know some things are named poorly, but people (lower case p) is the name of my DefaultListModel and People (capital P) is the name of my ArrayList. Basically, I just want to delete a block of 4 lines from an array. So, the position in the array, and the 3 after it.
While List and ArrayList don't have a direct (and accessible) removeRange() method, the need for such a method is removed by providing the subList() method.
subList() provides a view into a part of the original List. The important part to notice is that modifying the returned List will also modify the original List. So to remove the elements with the indices index to index+3, you could do this:
myList.subList(index, index+4).clear();
Note that the second argument of subList() is exclusive, so this subList() call will return a List with a size of 4.
This is an odd requirement. Deleting 3 items after it? How are they related to each other? They must be somehow related to each other. It sounds like that you have a contact list which looks like this:
List<String> contacts = new ArrayList<String>();
contacts.add("John Doe");
contacts.add("Main street 1"); // His street.
contacts.add("New York"); // His city.
contacts.add("555 123 456 789"); // His phone.
// etc..
Is this true? Then you should really consider grouping the related elements into another real-world representing object. You could create a Javabean class Contact which look like this:
public class Contact {
private String name;
private String street;
private String city; // You could consider another Address class for street and city as well.
private String phone;
// Add/generate getters and setters.
public Contact() {
// Keep default constructor alive.
}
public Contact(String name, String street, String city, String phone) {
this.name = name;
this.street = street;
this.city = city;
this.phone = phone;
}
}
This way you just end up with
List<Contact> contacts = new ArrayList<Contact>();
contacts.add(new Contact("John Doe", "Main Street 1", "New York", "555 123 456 789"));
// etc..
so that you can just remove a single real Contact by index.
You could even make it a property of People:
public class People {
private List<Contact> contacts;
// +getter +setter
}
Try to think OO.
Joachim's answer gives a good way of removing directly from an ArrayList, but I suspect you really want to remove the range directly from the model. DefaultListModel has a removeRange method:
int index = contactList.getSelectedIndex();
people.removeRange(index, index + 4);
I would expect that to have the right behaviour, removing the items from the underlying list as well. Assuming that's the case, that would be the best way of doing it I suspect. Then again, I don't know Swing very well :)
Try,
people.subList(index, index+4).clear()
Related
I'm sorry if this has been asked but I couldn't find something similar from google search so here goes. Say I have two objects
Notebook
public class NoteBook {
private String name;
private String description;
public NoteBook(String name, String description) {
this.name = name;
this.description = description;
}
}
and notes
public class Note {
private String sourceNoteBook
private String name;
private String category;
private String details;
public Note(String sourceNoteBook,String name, String category, String details) {
this.sourceNoteBook = sourceNoteBook;
this.name = name;
this.category = category;
this.details = details;
}
}
In the program the user can create a number of NoteBook objects and each NoteBook stores a variable number of Notes. Ultimately I would like to add a search function that can search for notes by category or name and return a list of the found notes.
Normally I would use 2 For loops to iterate through the list of notebooks and then iterate through the list of notes for each notebook and compare strings. something like this:
For (NoteBook noteBook: noteBooks) {
For(Note note :noteBooks.getNoteList){
if (note.getCategory().contains(someString)) {
matchingNotes.add(notes);
}
}
}
However I now want to be able to delete notes from the matchingNotes list such that the note in the original notebook is also deleted.
Whats the best way of storing and searching these two class such that I can implement such a function.
EDIT:
Just for clarification , the end result is that I would like the user to be able to search for a category of notes across all the notebooks ,the program will then return a list of notes matching that category. He/she can then delete a note from that list such that it is also deleted in the original notebook. E.g. completely removed from the program.
Why don't you just store the notebook information in note class?
public class Note {
private NoteBook sourceNoteBook;
private String name;
private String category;
private String details;
public Note(NoteBook sourceNoteBook,String name, String category, String details) {
this.sourceNoteBook = sourceNoteBook;
this.name = name;
this.category = category;
this.details = details;
}
}
Every data manipulation to note will always affect the notebook which store it
Iterator:
Probably the simplest solution. And since java is using Iterators under the hood in foreach loops, the performance would be the same.
For (NoteBook noteBook: noteBooks) {
Iterator<Note> it = noteBooks.getNoteList().iterator();
while (it.hasNext()) {
Note note = it.next();
if (note.getCategory().equals(someString)) {
it.remove();
}
}
}
SQL:
This would be optimal. However even using something lightweight, such as H2, or SQLite would require refactoring. And also is not an option in very lightweight applications.
Efficient:
If you only search by category, or name, you could use 2 maps:
Map<String, Note> notesByCategory;
Map<String, Note> notesBytName
This would require O(n) memory to store the maps, but would have very efficient lookups in O(1) time (compared to the current O(n)). I would avoid this solution, because it is very easy to achieve incosistent state between content of notes and the maps.
EDIT:
var newNoteNames = newList.stream().map(Note::getName).collect(Collectors.toSet());
var oldNoteNames = noteBooks.stream().flatMap(Notebook::getNodeList).map(Note::getName).collect(Collectors.toSet());
var removedNames = oldNoteNames.removeAll(newNoteNames);
for (var removedName : removedNames) {
for (NoteBook noteBook: noteBooks) {
Iterator<Note> it = noteBooks.getNoteList().iterator();
while (it.hasNext()) {
Note note = it.next();
if (note.getName().contains(removedName)) {
it.remove();
}
}
}
}
edit my answer
you can create a map when the key is the note and the value is the notebook keySet will returned to the user and once he selected the key you have the value to know from which notebook to delete and you have the key that you can delete the note. is that what you meant?
I have a Course class which has a method to add Items, which can be a note, an assignment, a URL, or just a generic item. All Items are kept in an ArrayList which the Course that created the list keeps up with. My question is from an item inside this ArrayList, how do I get the printLogger that I have attached to the course object in order to attach it to an item when the Item is created?
this from my Course:
public class Course {
private ArrayList<Item> items;
public PrintLogger p1 = null;
public Course(String code, String name) {
this.code = code;
this.name = name;
items = new ArrayList<>();
}
void add(Item item) {
items.add(item);
if (hasPrintLogger() == true) {
log(PrintLogger.INFORMATIONAL, "Adding " + item.toString());
}
}
And Im trying to have in the code that the assignment constructor runs a way to attach the same printLogger that is already on the course.
You could store a reference to the proper Course object in each of the items in the List.
You could also wrap the ArrayList class in your own class and add a field that points to the Course it belongs to if you need it to be a relationship between the List and the Course instead of between the items in the List and the Course.
You could also search each Course object in your system and check if it contains the List in question. However, this solution would scale badly.
I have an assignment for my class to sort a LinkedList that we made previously using the insert sort method. We created the List by reading in an excel file with 5 contributors listed. I realize this sounds like a repeat question...however, all of the samples I can find deal with Integers or arrays, nothing that I can find deals with strings or with a LinkedList like the one I am using. The other problem, the examples I do find that deal with more than just integers assume you made the list "from scratch", using Head and Node and stuff like that...as you can see in my code, I did not make mine from scratch, I just used the build in Java utility to make mine. Anyways, my code may not be super efficient, but I got a 100 on every assignment so far, so it's good enough for the school I guess, but any suggestions to make it better are welcome as well. I am a beginner to programming, only experience I have is previous classes. So, here is my code:
import java.io.*;
import java.util.*;
public class ChrisJohnson_Unit3_IP {
static class Contributor{ //create class to store contributor information
//declare variables
private String firstName;
private String lastName;
private String country;
private String phone;
private double contribution;
private int id;
//methods for setting variable values
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getLastName(){
return lastName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getCountry(){
return country;
}
public void setCountry(String country){
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone){
this.phone = phone;
}
public double getContribution(){
return contribution;
}
public void setContribution(double contribution){
this.contribution = contribution;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public void Print(){//method to print class objects
System.out.printf("%-10s %-10s %-8s %-15s %s %-15s %d %n", firstName, lastName, country,
phone, "$", contribution, id);
}
}//end Contributor class
static LinkedList contributorList = new LinkedList(); //create new Contributor Linked List
static Hashtable<String, Contributor> memberID = new Hashtable<>();//create new Hash Table
public static void main(String[] arg) throws Exception {
String response;
String ID;
Contributor contributorData = null;
Scanner in = new Scanner(System.in);
//print Welcome message and describe program to user
System.out.println("Welcome! This program will read your contributors.csv file "
+ "and store it into a list. \nTThe program will then sort the list and"
+ "print it for you to view/n");
System.out.println("Press enter to read the currently saved contributors.csv file...");
in.nextLine();
BufferedReader File =
new BufferedReader(new FileReader("contributors.csv"));
String dataRow = File.readLine(); // Read first line.
// The while checks to see if the data is null. If
// it is, end of file has been reached. If not,
// data will be processed.
while (dataRow != null){//While to read contributors.csv file and store in Contributor object
String[] data = dataRow.split(",");
contributorData = new Contributor(); //create new Contributor object
//store data into Contributor object
contributorData.setFirstName(data[0]);
contributorData.setLastName(data[1]);
contributorData.setCountry(data[2]);
contributorData.setPhone(data[3]);
contributorData.setContribution(Double.parseDouble(data[4]));
contributorData.setId(Integer.parseInt(data[5]));
ID = Integer.toString(contributorData.getId());
contributorList.push(contributorData);//add object to top of contributorList
memberID.put(ID,contributorData);//add contributor ID to key element of Hash Table
dataRow = File.readLine(); // Read next line of data.
}//end While to read contributors.csv file
File.close();//close CSV file
System.out.println("Here is your unsorted contributor list:\n");
//call Print method to print the list
System.out.printf("%-10s %-10s %-8s %-15s %-17s %s %n", "First", "Last",
"Country", "Phone #", "Contribution", "ID");
Iterator<Contributor> iter = contributorList.iterator();
while(iter.hasNext()){
iter.next().Print();
}//end while
System.out.println("Thank you for using this program!");
} //main()
}//end ChrisJohnson_Unit3_IP class
Again, the List has to be sorted by Name using the insert sort method. I understand the basic concept of the sort method, but honestly have no clue how to implement it here. I'm not looking for someone to do my homework for me, just give me a push in the right direction. Any help would be greatly appreciated, if you need anymore information please let me know. This assignment is due Monday, so hopefully someone is able to help me out by then. And yes, I have already written my instructor asking for help, I have been out of town all week so I have been trying to play catchup. Thank you for taking the time to read my question
First of all, I should say that doing an insertion sort on a linked list is totally pointless. Secondly, you could do something like the following, if you add a getName method that concatenates first and last names of the contributor (you can concatanate while sorting, but your code will be messier).
for( int i = 1; i < contributorList.size(); i++)
{
int j = i;
Contributor tmp;
while( j > 0 && contributorList.get(j-1).getName().compareTo( contributorList.get(j).getName()) > 0)
{
tmp = contributorList.remove( j);
contributorList.add( j-1, tmp);
j = j - 1;
}
}
First change your contributorList to use the Generic type of the objects it holds. That is LinkedList<Contributor>;. Second change the Object to implement Comparable. That is class Contributor implements Comparable<Contributor> and implement method public int compareTo(Contributor other). Third, pick a sorting method and implement it using compareTo to compare the objects for sorting.
Use ListIterator to find the correct point to insert the element and to the insertion. This allows you to do the insertion sort more efficiently than with the "standard approach", which would run in O(n³), since get and set runs in O(i) for index i. (The inner loop would run in O(i²), since O(1+2+...+i) = O(i²) and O(1²+2²+...+n²) = O(n³)).
Note that using a Iterator is enough to find the insertion point in O(n) and achieve O(n²) running time, but using ListIterator allows you to find and insert the element as well as remove the element for the next iteration of the outer loop iteration only a single iterator, if used in a clever way.
Using a Comparator to compare objects by a specified criterion also allows you to specify a criterion to sort by:
return value of comparator.compare(a, b) | meaning
-----------------------------------------------------------
0 | a == b
> 0 | a > b
< 0 | a < b
In java 8 you can easily create a Comparator given the method reference to a method returning the sort criterion given a object:
Comparator<Contributor> comparator = Comparator.comparing(Contributor::getLastName);
Without using method references this can be done using compareTo of a object implementing the Comparable interface, like String:
Comparator<Contributor> comparator = new Comparator<Contributor>() {
#Override
public int compare(Contributor o1, Contributor o2) {
return o1.getLastName().compareTo(o2.getLastName());
}
};
This way you use the Strategy Pattern for the ordering relation allowing you to use different sortings by passing different Comparators. And it's also the way the Collections class allows you to sort Lists with arbitrary contents, see Collections.sort(List, Comparator).
I'm doing a project on web scraping using ArrayLists. When I scrape the info, it comes back as item [0] = pencil, item [1] = $1.50. I would like these items to be together, or if possible it would be even better if the prices and item each had their own id, but each was somehow linked together so that I could reference each one separately. Also, sometimes when scraping I get item [2] = paper, item [3] = $5.00, item [4] = wide bound college ruled, where item [4] represents an optional description that was included with the item that would need to be included in the ArrayList or in a separate ArrayList linked by ids as before. Any ideas are appreciated.
If you only need the name and the price, your best solution is to use a Map, works kind of like an ArrayList<T>, but instead of a single element you have a couple <Key,Value>, like <pencil, 1,50>.
If you need more than two values I would suggest to create your own class, for example:
public class Item {
private String name;
private double price;
private String description;
}
With all the extra methods you need, then declare your ArrayList like this;
ArrayList<Item> items = new ArrayList<>()
It would be better to make a class Item width variables for your name, price and description.
Then you can make an ArrayList to store all of your items.
You should model the object as a class, for example "item", and add each value as a variable of the class. For example:
public class item{
private String name;
private double price;
private String description; //If there's no description it could be null
// Constructor
...
// Getters and setters
...
}
You will need to format the price as a double.
I have a class Passengers which has member properties String name, int health, and String disease with setter and getter methods. The disease variable will initially hold null. Here's that class
public class Passengers
{
private String name;
private int health;
private String disease;
public Passengers(String _name, int _health, String _disease)
{
name = _name;
health = _health;
disease = _disease;
}
public void setHealth(int _health)
{
health = _health;
}
public void setDisease(String _disease)
{
disease = _disease;
}
public String getName()
{
return name;
}
public int getHealth()
{
return health;
}
public String getDisease()
{
return disease;
}
}
What I want to know is how I could add new strings onto this variable, and then how to take away. For example, a passenger Bill starts at null for his diseases, and then contracts malaria and the cold. Bill's disease variable should now hold malaria, cold. Now say the user chooses to treat Bill's malaria. How would I
1) add malaria and cold
2) subtract just malaria from disease?
Whenever I attempt to change the disease with
passengers[index].setDisease() = null;
it says "error: method setDisease in class Passengers cannot be applied to given types:
required: String
found: no arguments"
I would reccomend making disease a Set of Strings.
Set<String> diseases = new HashSet<String>();
void addDisease(String disease) {
diseases.add(disease);
}
void removeDisease(String deisease) {
diseases.remove(disease);
}
Sets are "better", in this case, than other Collections because they cannot hold duplicates.
You should give the class a List<String> such as an ArrayList<String> and put the diseases in this List.
Better still, create a class or enum of Disease and have your Passenger class use a List<Disease> and avoid over-use of String. You could then give the class public addDisease(Disease disease) and removeDisease(Disease disease) methods.
Incidentally, your class above should be named Passenger, the singular, not Passengers, the plural, since it represents the concept of a single Passenger.
For your requirement if you are using List like ArrayList you can access your elements(disease names) by index, but it will allow duplicate data to be inserted(same disease may be added multiple times, it will unnecessary increase in number of diseases and may arise some problems).
If you use Set like HashSet it will allow unique element only, so no issues related to duplicated entries but at the same time you can't access a particular disease by index (if you need so, as of now I am not aware of your further requirement).
So as best of my knowledge I suggest you to use LinkedHashSet(HashSet with Linked approach) it will provide you FIFO order without duplicate insertion problem.