问题
If I have an ArrayList of books and I want to delete a certain number of books only if they are different (using equals). How can I approach the problem?
For example, if I have 3 different books and my quantitytoremove is 3.. then those 3 books have to be deleted. Assuming quantitytoremove can't be higher than the number of DIFFERENT books inside the array.
I tried something like this but I know there are issues with what I wrote. Is there a function available with streams or else that can help me?
public Basket removeDifferent(int quantitytoremove) {
int removed=0;
for (int i = 0; i < this.numberBooks && removed<quantitytoremove ; i++) {
for (int j = i+1; j < this.numberBooks && removed<quantitytoremove; j++) {
if (!(this.BooksArray.get(i).equals(this.BooksArray.get(j)))) {
Book Book_i= this.BooksArray.get(i);
Book Book_j= this.BooksArray.get(j);
this.BooksArray.remove(Book_i);
this.BooksArray.remove(Book_j);
removed=removed+2;
this.numberBooks=numberBooks-2;
i=0;j=1;
}
}
}
}
回答1:
First, @Override equals() in class Foo to decide what's the attributes that make two objects equals and remove using recursion
Explain how recursion works
qn represents how many removes are done
Starting point i = 0 j = 1 and recursion till the base condition reached
Step 1, Base condition: if i or j exceeded the size of the array or qn exceeded the quantityToRemove return qn
Step 2, Check equality if array elements of i and j not equal then remove and increment qn and decrement j to avoid missing element
Step 3 for all i and increment j Repeat to Step 3 till reaching the base condition
Step 4 increment ++i
Step 5 start new recursion with increment i and start j from i+1
After the recussion has finished, check if qn not exceeded the quantityToRemove and remove from the array if contains 1 book. this for a case when you have different 4 books and want all of them to be removed
...
Trace
i = 0, j = 1, 2, ...., N
i = 1, j = 2, 3, ...., N
i = 2, j = 3, 4, ...., N
i = 3, j = 4, 5, ...., N
...
static class Book {
int id;
String title;
public Book(int id, String title) {
this.id = id;
this.title = title;
}
@Override
public boolean equals(Object obj) {
Book other = (Book) obj;
return this.title.equals(other.title);
}
@Override
public String toString() {
return id + ": " + title;
}
}
public static void main(String[] a) {
Book b1 = new Book(1, "b1");
Book b2 = new Book(2, "b2");
Book b3 = new Book(3, "b3");
Book b4 = new Book(4, "b4");
Book b5 = new Book(1, "b1");
List<Book> list = new ArrayList<>();
list.add(b1);
list.add(b2);
list.add(b3);
list.add(b4);
list.add(b5);
list.add(new Book(1, "b1"));
list.add(new Book(1, "b1"));
list.add(new Book(1, "b1"));
System.out.println(list);
removeDifferent(list, 2);
System.out.println(list);
}
static void removeDifferent(List<Book> booksArray, int quantityToRemove) {
int qn = removeDifferent(booksArray, quantityToRemove, 0, 0, 1);
if (booksArray.size() == 1 && qn < quantityToRemove)
booksArray.remove(0);
}
static int removeDifferent(List<Book> booksArray, int quantityToRemove, int qn, int i, int j) {
if (i >= booksArray.size() || j >= booksArray.size() || qn >= quantityToRemove)
return qn;
if (!booksArray.get(i).equals(booksArray.get(j))) {
booksArray.remove(j);
j--;
qn++;
}
qn = removeDifferent(booksArray, quantityToRemove, qn, i, 1 + j);
++i;
qn = removeDifferent(booksArray, quantityToRemove, qn, i, i + 1);
return qn;
}
, output
[1: b1, 2: b2, 3: b3, 4: b4, 1: b1, 1: b1, 1: b1, 1: b1]
[1: b1, 4: b4, 1: b1, 1: b1, 1: b1, 1: b1]
, And for this input
Book b1 = new Book(1, "b1");
Book b2 = new Book(2, "b2");
Book b3 = new Book(3, "b3");
Book b4 = new Book(4, "b4");
List<Book> list = new ArrayList<>();
list.add(b1);
list.add(b2);
list.add(b3);
list.add(b4);
System.out.println(list);
removeDifferent(list, 4);
System.out.println(list);
, output
[]
回答2:
Use Java Stream and removeIf:
List<Book> books = new ArrayList<>();
// init the books
List<Book> distinctBooks = books.stream().distinct().collect(Collectors.toList());
int quantitytoremove = 3;
List<Book> needToDeleted = new ArrayList<>();
for (int i = 0; i < quantitytoremove; i++) {
needToDeleted.add(distinctBooks.get(i));
}
books.removeIf(needToDeleted::contains);
System.out.println(books);
回答3:
Steps to be followed:
- Put
bookListinto aSetto remove the duplicate elements and then create aList,booksout of theSet. - Add
quantityToRemoveelements frombooksto anotherList,toBeRemovedList. - Add all elements, except one item each also belonging to
tobeRemovedListfrombookListto anotherList,toBeReturnedList.
Note: You can replace the first step using Stream API as shown below:
static List<Book> removeDifferent(List<Book> bookList, int quantityToRemove) {
// Put `bookList` into a Set to remove the duplicate elements and then create
// a List, `books` out of the Set
List<Book> books = new ArrayList<Book>(new HashSet<Book>(bookList));
// You can replace the above code with Stream code given below:
// List<Book> books = bookList.stream().distinct().collect(Collectors.toList());
// Add `quantityToRemove` elements from `books` to another List,
// `toBeRemovedList`
List<Book> toBeRemovedList = new ArrayList<Book>();
for (int i = 0; i < quantityToRemove; i++) {
toBeRemovedList.add(books.get(i));
}
// Add all elements, except one item each also belonging to `tobeRemovedList`
// from `bookList` to another List, `toBeReturnedList`
List<Book> toBeReturnedList = new ArrayList<Book>();
int c = 0;// Counter
for (Book book : toBeRemovedList) {
for (int i = c; i < bookList.size(); i++) {
if (book.equals(bookList.get(i))) {
c = i;
break;
}
toBeReturnedList.add(bookList.get(i));
}
c++;
}
for (int i = c; i < bookList.size(); i++) {
toBeReturnedList.add(bookList.get(i));
}
// Return toBeReturnedList
return toBeReturnedList;
}
Demo:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
class Book {
int id;
public Book(int id) {
this.id = id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object obj) {
Book other = (Book) obj;
return this.id == other.id;
}
@Override
public String toString() {
return "Book [id=" + id + "]";
}
}
public class Main {
public static void main(String[] args) {
List<Book> books = new ArrayList<Book>();
books.add(new Book(1));
books.add(new Book(1));
books.add(new Book(1));
books.add(new Book(2));
books.add(new Book(3));
List<Book> updatedList = removeDifferent(books, 3);
// Display updated list
updatedList.stream().forEach(System.out::println);
}
static List<Book> removeDifferent(List<Book> bookList, int quantityToRemove) {
// Put `bookList` into a Set to remove the duplicate elements and then create
// a List, `books` out of the Set
List<Book> books = new ArrayList<Book>(new HashSet<Book>(bookList));
// You can replace the above code with Stream code given below:
// List<Book> books = bookList.stream().distinct().collect(Collectors.toList());
// Add `quantityToRemove` elements from `books` to another List,
// `toBeRemovedList`
List<Book> toBeRemovedList = new ArrayList<Book>();
for (int i = 0; i < quantityToRemove; i++) {
toBeRemovedList.add(books.get(i));
}
// Add all elements, except one item each also belonging to `tobeRemovedList`
// from `bookList` to another List, `toBeReturnedList`
List<Book> toBeReturnedList = new ArrayList<Book>();
int c = 0;// Counter
for (Book book : toBeRemovedList) {
for (int i = c; i < bookList.size(); i++) {
if (book.equals(bookList.get(i))) {
c = i;
break;
}
toBeReturnedList.add(bookList.get(i));
}
c++;
}
for (int i = c; i < bookList.size(); i++) {
toBeReturnedList.add(bookList.get(i));
}
// Return toBeReturnedList
return toBeReturnedList;
}
}
Output:
Book [id=1]
Book [id=1]
Result for removeDifferent(books, 2):
Book [id=1]
Book [id=1]
Book [id=3]
Result for removeDifferent(books, 1):
Book [id=1]
Book [id=1]
Book [id=2]
Book [id=3]
来源:https://stackoverflow.com/questions/61646691/how-to-remove-not-equals-objects-using-arraylist-in-java