简体   繁体   English

访问ArrayList中object的元素

[英]Accessing elements of object in ArrayList

I was wondering if I could get some advice please.我想知道我是否可以得到一些建议。 I have the following code:我有以下代码:

 private static int getIndex(String regneeded) {

        System.out.println("The reg passed to getIndex method is:" + regneeded);
         if (arraylist.contains(regneeded)) {
             int pos = arraylist.indexOf(regneeded);
             System.out.println("The position of the vehicle in the array list is:" + pos);
         }else {return -1;}
         return 0;
  }

What I am trying to do is search an Array of DeliveryVehicles, for a specific reg number (that I pass to the method) and then say what position in the ArrayList the object that contains this reg is located.我想做的是搜索 DeliveryVehicles 数组,寻找特定的注册编号(我传递给方法),然后说出 ArrayList 中的 position 包含此注册的 object 所在的位置。

I know I have an issue as I am searching for a string within an ArrayList and what I have in my ArrayList are objects.我知道我有一个问题,因为我在 ArrayList 中搜索一个字符串,而我在 ArrayList 中拥有的是对象。 So, just looking for any advice while I continue to research.所以,在我继续研究的同时寻找任何建议。

Thank you in advance.先感谢您。 Apologies if this is basic I am very new to Java.抱歉,如果这是基本的,我是 Java 的新手。

EDIT: To include further information on the objects contained in the ArrayList.编辑:包括有关 ArrayList 中包含的对象的更多信息。

DeliveryVehicle objects are contained in the ArrayList. Each contain registration numbers (they have other attributes but I'm focusing on the registration number to understand this issue first). DeliveryVehicle 对象包含在 ArrayList 中。每个对象都包含注册号(它们具有其他属性,但我首先关注注册号以了解此问题)。 There are setters (setRegNum()) and getters (getRegNum()) in the base class DeliveryVehicle for the registration number, and I pass the registration number to the constructor when I create my vehicle object as follows:在注册号的基础 class DeliveryVehicle 中有设置器 (setRegNum()) 和获取器 (getRegNum()),我在创建车辆 object 时将注册号传递给构造函数,如下所示:

 DeliveryBike myVehicle = new DeliveryBike("21D789");
        arraylist.add(myVehicle);

I have extended the base class to include a DeliveryBike class (as seen).我已经扩展了基础 class 以包括 DeliveryBike class(如图所示)。 The code I originally posted was a method in my controller class. So, I suppose I'm confused how to access the registration number within the DeliveryBike object.我最初发布的代码是我的 controller class 中的一个方法。所以,我想我很困惑如何访问 DeliveryBike object 中的注册号。

Thank you.谢谢你。

You are using the wrong data structure for the problem.您针对该问题使用了错误的数据结构。 Identifying objects with keys such as strings is the perfect use case for a Map. Because strings can be hashed, you can use java.util.HashMap :使用字符串等键识别对象是 Map 的完美用例。因为可以对字符串进行哈希处理,所以您可以使用java.util.HashMap

import java.util.HashMap;
import java.util.Map;

public class Main
{
    static class DeliveryBike {public String s; public DeliveryBike(String s) {this.s=s;}} 

    public static void main(String[] args)
    {
        Map<String,DeliveryBike> vehicles = new HashMap<>();
        vehicles.put("21D789",new DeliveryBike("21D789"));
        System.out.println(vehicles.get("21D789").s);
    }
}

If you can't change it from being an ArrayList because it is passed in from the outside, put it in a map first and then you can search that map multiple times.如果你不能把它从ArrayList改成ArrayList,因为它是从外面传入的,那么先把它放在map中,然后你可以多次搜索map。

If you do insist on using an ArrayList, because you get it passed from the outside and you will always use it just once, you could also use streams and a filter:如果你坚持使用 ArrayList,因为你从外部传递它并且你总是只使用它一次,你也可以使用流和过滤器:

import java.util.ArrayList;
import java.util.List;

public class Main
{
    static class DeliveryBike {public String s; public DeliveryBike(String s) {this.s=s;}} 

    public static void main(String[] args)
    {
        List<DeliveryBike> vehicles = new ArrayList<>();
        vehicles.add(new DeliveryBike("21D789"));
        System.out.println(vehicles.stream().filter(x->x.s=="21D789").findFirst().get().s);
    }

}

Warning警告

In real world code, you would need to guard against the key not being there in both cases.在现实世界的代码中,您需要防止密钥在两种情况下都不存在。 With the map, vehicles.get() can return null, and with the filter, findFirst() can return an empty optional.对于 map,vehicles.get() 可以返回 null,对于过滤器,findFirst() 可以返回一个空的可选值。

You can define generic indexOf method like so:您可以像这样定义通用的indexOf方法:

private static <T,E> int indexOf(List<? extends T> list, BiPredicate<T,E> pred, E e) {
    int i = list.size();
    while (--i >= 0 && !pred.test(list.get(i), e)) {
        // nothing
    }
    return i;
}

You can define the predicate for the reg number:您可以为注册号定义谓词:

private static BiPredicate<DeliveryVehicle,String> BY_REGNUMBER
        = (dv,e)->dv.getRegNumber().equals(e);

You would use it as follows:您将按如下方式使用它:

    list.add(new DeliveryBike("1"));
    list.add(new DeliveryBike("2"));
    list.add(new DeliveryBike("3"));
    list.add(new DeliveryBike("4"));
    list.add(new DeliveryBike("5"));
    System.out.println(indexOf(list, BY_REGNUMBER, "1"));
    System.out.println(indexOf(list, BY_REGNUMBER, "2"));
    System.out.println(indexOf(list, BY_REGNUMBER, "3"));
    System.out.println(indexOf(list, BY_REGNUMBER, "4"));
    System.out.println(indexOf(list, BY_REGNUMBER, "5"));
    System.out.println(indexOf(list, BY_REGNUMBER, "6"));

UPDATE:更新:

An alternative using a function to extract the attribute instead of a predicate:另一种方法是使用 function 来提取属性而不是谓词:

private static <T,E> int indexOf(List<? extends T> list, Function<T,E> attr, E e) {
    int i = list.size();
    while (--i >= 0 && !attr.apply(list.get(i)).equals(e)) {
        // nothing
    }
    return i;
}

You would you it like this:你会喜欢这样:

    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "1"));
    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "2"));
    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "3"));
    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "4"));
    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "5"));
    System.out.println(indexOf(list, DeliveryVehicle::getRegNumber, "6"));

Well, you would have to walk over the DeliveryVehicle s and check whether the registration number of the object is equal to the registration number you're searching:那么,您将不得不遍历DeliveryVehicle并检查 object 的注册号是否等于您正在搜索的注册号:

int getIndex(String search) {
    for (int i = 0; i < arraylist.size(); i++) {
        if (Objects.equals(arraylist.get(i).getRegNum(), search)) {
            System.out.println("The position of the vehicle in the arraylist is: " + i);
            return i;
        }
    }
    return -1;
}

Note that contains and indexOf search for a whole object within a list, but they are not suitable for searching for objects with a specific attribute .注意containsindexOf在列表中搜索整个 object ,但它们不适合搜索具有特定属性的对象。

For each object in the arraylist , the attribute registrationNumber is compared to the string you're search ing, and if they match, print something to the console and immediately return i , which is the position of the found element.对于 arraylist 中的每个arraylist ,将属性registrationNumber与您正在search的字符串进行比较,如果它们匹配,则向控制台打印一些内容并立即返回i ,即找到的元素的 position。

Otherwise, return -1 , which is a sentinel value meaning that there is no object with that registration number.否则,返回-1 ,这是一个标记,表示没有 object 具有该注册号。


Note that there are data structures which are a better choice for this kind of scenario, like using a Map or Streams, but I don't think that is in scope of the question.请注意,对于这种情况,有些数据结构是更好的选择,例如使用 Map 或 Streams,但我认为这不在问题的 scope 中。

There are differente approaches.有不同的方法。

1- You could loop through all elements and compare values 1-您可以遍历所有元素并比较值

private static int getIndex(String regneeded) {
    for (DeliveryBike vehicle: arrayList) {
        if (vehicle.getRegNumber().equalsIgnoreCase(regneeded)) {
            return arrayList.indexOf(vehicle);
        }
    }

    return -1;
}

2- You could override hashCode and equals methods in your DeliveryBike class 2- 您可以覆盖 DeliveryBike 中的hashCodeequals方法 class

// inside your DeliveryBike class add
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    DeliveryBike that = (DeliveryBike) o;
    return Objects.equals(regNumber, that.regNumber);
}

@Override
public int hashCode() {
    return Objects.hash(regNumber);
}
private static int getIndex(String regneeded) {
    DeliveryBike searchItem = new DeliveryBike(regneeded);
    return arrayList.indexOf(searchItem);
}

If I'm not mistaken, equals method is used in collections like List, Set and Map in order to know if an element is already included and hashCode method is used by Map collections in order to find the object associated with the key.如果我没记错的话,在 collections 中使用了equals方法,如 List、Set 和 Map 以了解是否已包含一个元素,而 Map collections 使用了hashCode方法以找到与键关联的 object。

In this case you'd only need the equals method but it's common to override both at the same time.在这种情况下,您只需要equals方法,但通常同时覆盖两者。


Also I would make two functions for your purpose, one would return the index of the element, the other would display a text using that index.此外,我会为您的目的制作两个函数,一个会返回元素的索引,另一个会使用该索引显示文本。 That way you could reuse your code if the project gets bigger!这样,如果项目变得更大,您就可以重用您的代码!

private static int getIndex(String regneeded) {
    DeliveryBike searchItem = new DeliveryBike(regneeded);
    return arrayList.indexOf(searchItem);
}

private static void showMessage(int index, String regneeded) {
    System.out.println("The position of the vehicle with reg " + regneeded + " in the array list is:" + pos);
}

Hope this helps you!希望这对你有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM