Я пытаюсь создать программу списка дел, и у меня возникают проблемы с поиском способа удаления элементов путем поиска определенного элемента.
Я пытаюсь реализовать indexOf()
, который будет возвращать индекс элемента, содержащего элемент, искомый в ArrayList of Items, но вместо этого он возвращает только -1, а не найден.
Я перегрузил функцию в своем классе ToDo и перегрузил equals(Object o) и hashCode() в своем классе Item.
Любая помощь будет принята с благодарностью.
import java.util.*;
import java.lang.*;
public class ToDo {
ArrayList<Item> TodoList = new ArrayList<>();
static String [] itemData = new String[100]; //to index items added to list
//itemData = new String[100];
static int size=0;
public void addItem(String item, String category, int priority)
{
TodoList.add(new Item(item,category,priority));
itemData[size] = item; //for indexing
size++;
}
//remove item at specified index spot
private void removeItem(int i )
{
TodoList.remove(i);
}
public void getList()
{
for (Item item : TodoList)
{
System.out.println(item.toString());
}
}
public int getIndex(String item)
{
return (TodoList.indexOf(item));
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (itemData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(itemData[i]))
return i;
}
return -1;
}
public void print() {
System.out.println("To-do List: ");
System.out.println("-----------");
getList();
if (TodoList == null) {
System.out.println("You're all done for today!");
}
}
public static void main(String[] args) {
ToDo todo = new ToDo();
todo.addItem("Get pickles", "Shopping", 2);
todo.addItem("Read book", "School", 3);
todo.addItem("Send letter", "Other", 1);
todo.addItem("Buy planner", "School", 4);
todo.addItem("Get potatoes", "Shopping", 3);
todo.print();
System.out.println("------------");
//todo.removeItem("Read book","School","3");
//todo.removeItem(1);
System.out.println("INDEX OF READ BOOK (1) :" + todo.getIndex("ReadBook"));
//todo.removeItem(todo.getIndex("ReadBook"));
//todo.print();
System.out.println("SIZE: " + size);
}
}
public class Item {
public int i;
private String item;
private String category;
private int priority;
//default constructor to initialize
public Item(String item, String category, int priority){
this.item = item;
this.category = category;
this.priority = priority;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public void setPriority(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
//used in order to overload indexOf() method
//*****************************************************
@Override
public boolean equals(Object o) {
if (o instanceof Item) {
//item comparison
Item mo = (Item)o;
return mo.item.equals(item);
}
return false;
}
public int hashCode() {
return java.util.Objects.hashCode(item);
}
// *****************************************************
public String translatePriority()
{
if (priority == 1)
return "low";
else if (priority == 2)
return "medium";
else if (priority == 3)
return "high";
else if (priority == 4)
return "urgent";
else
return "invalid priority";
}
public String toString() {
return "Category : " + category + " || Priority Level: " + translatePriority() + "\nTask : " + item + "\n";
}
}
И вы не перегружаете indexOf — это было бы только в том случае, если бы вы расширяли класс или реализовывали интерфейс, который уже определил его.
Вы передаете строку TodoList.indexOf(item)
, но Item.equals()
обрабатывает только Item
s.
Существует ряд проблем с вашим кодом: Вы вызываете indexOf() класса ArrayList, вам нужно перейти на это, чтобы вызвать свой собственный метод
public int getIndex(String item)
{
return (indexOf(item));
}
и эта строка кода не будет соответствовать ни одному элементу примера, поэтому она вернет -1
todo.getIndex("ReadBook")
может ты хотел написать?
todo.getIndex("Read book")
Довольно много вопросов, чтобы указать здесь.
Вы объявили TodoList
ArrayList<Item>
.
Итак, ваш код:
public int getIndex(String item) {
return (TodoList.indexOf(item));
}
Всегда будет возвращать -1. Список содержит Item
, а не строки.
Вы объявили массив для хранения имен элементов «для индексации». Это не имеет особого смысла. Перебор массива в поисках имени займет столько же времени, сколько и просмотр исходного списка. И у вас будет проблема с синхронизацией индексов.
Лучший вариант — просто сохранить элементы в списке и найти элемент с заданным именем:
IntStream.range(0, ToDoList.size())
.filter(i -> ToDoList.get(i).getItem().equals(item))
.findAny().orElse(-1);
Все экземпляры Item содержатся в ToDoList ArrayList. Очевидно, что все, к чему вам нужно получить доступ, можно сделать с помощью этого списка объектов Item. Если ваш поиск должен быть специфичным для переменной экземпляра Item#item, вам нужно будет выполнить итерацию по коллекции ToDoList и сравнить критерии поиска (ReadBooks) с тем, что может содержаться в любом экземпляре Item#item. Если обнаружено совпадение, процесс итерации останавливается и возвращается текущий индекс этой итерации. Это означает, что для вашего метода getIndex() требуются изменения:
public int getIndex(String item) {
int index = -1;
String itemString = item.replaceAll("\\s+", "").toLowerCase();
for (int i = 0; i < TodoList.size(); i++) {
String listItem = TodoList.get(i).getItem().replaceAll("\\s+", "").toLowerCase();
// I think it's better to use the String#contains() method
// instead of the String#indexOf() method.
if (listItem.contains(itemString)) {
index = i;
break;
}
}
return index;
}
Вы можете заметить, что пробелы удалены из любых предоставленных критериев поиска, а строка приведена к нижнему регистру. То же самое делается с каждым экземпляром строки Item#item, полученной в ходе итерации. Это делается для тех случаев, когда критерий поиска указан как "ReadBook"
, хотя экземпляр элемента явно заполнен "Read book"
. Приведенный выше код должен найти связь. Вы также заметите, что вместо метода String#indexOf() используется метод String#contains(). Я считаю, что это лучше подходит для этой конкретной ситуации.
Если вы предпочитаете, чтобы ваш поиск был более глобальным по всем переменным-членам экземпляра Item, вам лучше сравнить критерии поиска с экземпляром Item для toString(), например:
String listItem = TodoList.get(i).toString().replaceAll("\\s+", "").toLowerCase();
Однако было бы неплохо изменить формат возвращаемой строки Item#toString(), возможно, на что-то менее подробное, например:
@Override
public String toString() {
return new StringBuilder("").append(category).append(", ")
.append(translatePriority()).append(", ").append(item)
.toString();
}
Не используйте отдельный массив для вашего индекса. Просто просмотрите ArrayList элементов. И сделайте тип параметра indexOf фактическим типом, который вы хотите (String), а не Object. В противном случае ваш класс сложно использовать, так как неясно, что нужно передать этому методу.