简体   繁体   English

更改存储在ArrayList或HashMap中的对象的属性的最佳方法是什么?

[英]What's the best way to change attributes of objects stored in an ArrayList or HashMap?

I have to do a little exercise (homework, like a friendlist) in Java, and i'm a little stuck on one of the tasks that i have to implement in my program. 我必须在Java中做一些练习(如朋友列表一样的家庭作业),而我在程序中必须执行的一项任务上有些卡住。 The exercise is about storing some friend-objects with a variety of attributes in a container-class and implementing some methods in the container-class for various tasks on the friend-objects. 该练习是关于在容器类中存储一些具有各种属性的朋友对象,并在容器类中实现一些方法来实现朋友对象上的各种任务。

The overall exercise is not a problem at all, but i'm quite unconvinced that my solution is the way to go. 整体练习完全不是问题,但我完全不相信我的解决方案是正确的方法。 I hope you can give me some tips here. 希望您能在这里给我一些提示。

The method that is left over, should be something like a "updateFriend" method, with which you can set the value of a given attribute to a new value, straight from the container-class. 剩下的方法应该类似于“ updateFriend”方法,使用该方法可以直接从容器类将给定属性的值设置为新值。

I've already set up my friend-class with a handfull of attributes (eg prename, lastname, date of birth, adress, and so on) an getters/setters for all of them. 我已经为我的朋友班设置了一小部分属性(例如,姓,名,出生日期,地址等),这些属性都适用于所有这些。 I've also implemented the container-class (as an ArrayList), but i can't seem to find an elegant way to implement this specific method. 我还实现了容器类(作为ArrayList),但是我似乎找不到一种优雅的方式来实现此特定方法。 My updateFriend()-method right now takes three parameters. 我的updateFriend()方法现在带有三个参数。

1.The specific id of the friend-object 1.朋友对象的具体ID

2.The name of the attribute that i want to change 2.我要更改的属性名称

3.The new value of the attribute 3.属性的新值

It uses an enum to check if the entered attribute is an existing attribute and if yes, the method searches the ArrayList for the object that contains that attribute and should overwrite the existing value. 它使用一个枚举检查输入的属性是否为现有属性,如果是,则该方法在ArrayList中搜索包含该属性的对象,并应覆盖现有值。 It gets a little bulky, as i have implemented a switch on the enum, that calls the fitting setter-method for each attribute of the friend, if the type in attribute exists at all. 因为我在枚举上实现了一个开关,所以它有点笨拙,如果属性中的类型根本存在,它会为朋友的每个属性调用适合的setter方法。

So basically the friend-class looks like this: 因此,基本上,朋友班级是这样的:

public class Friend {

    private static int friendCount = 1;

    private String firstname;
    private String lastname;
    private LocalDate dateOfBirth;
    private String phonenumber;
    private String mobilenumber;
    private String eMail;
    private Adress home;
    private int friendID;

//Getters & Setters
...
}

The method that gives me problems in the container-class looks something like this at the moment: 目前在容器类中给我带来问题的方法如下所示:

public void updateFriend(int id, String toChange, String newValue)
{
    for(Attribute a : attribute.values())
      {
          if(String.valueOf(a).equalsIgnoreCase(toChange))
          {
              for(Friend f : friends)
              { 
                  int counter = 1;
                  if(f.getID() == id)
              {
                     switch(a)
                     {
                          case FIRSTNAME:
                         {
                         f.setPreName(neuerWert);
                           break;   
                        }
                   //a case for each attribute
               }

I'm quite certain that my take on the given method is messy, slow, and cumbersome. 我非常确定我对给定方法的看法是混乱,缓慢且麻烦的。 What would be an elegant way of solving this? 解决这个问题的一种优雅方法是什么? Excuse my wording and thanks in advance, greets. 打扰一下,我先谢谢,打招呼。

I would suggest 3 performance improvements. 我建议改善3个性能。

  1. Use HashMap instead of List with key as id . 使用HashMap代替键为idList Since, id will be unique, it will take O(1) time to get the relevant object for modification instead of spending O(n) time on List iteration. 由于id将是唯一的,因此将花费O(1)时间来获取要修改的相关对象,而不是在List迭代上花费O(n)时间。

  2. You can change the type of toChange parameter from String to enum . 您可以将toChange参数的类型从String更改为enum This will avoid enum to String conversion and then comparing it. 这将避免enumString转换,然后再进行比较。

  3. Since, you are already doing validation of the attribute to be modified and you must be following standard java convention while naming your getters and setters, you can use reflection to call the method on the Friend object by creating the method name from attribute name like set{Attributename} . 由于您已经在验证要修改的属性,并且在命名getter和setter时必须遵循标准的Java约定,因此可以通过反射来调用Friend对象上的方法,方法是从属性名称(如set{Attributename}创建方法名称set{Attributename}

Okay, lets start using the enum Attribute to handle all the changes (Since you already holding the attribute values) 好的,让我们开始使用枚举Attribute来处理所有更改(因为您已经保存了属性值)

Attribute Enum 属性枚举

public enum Attribute {

    FIRSTNAME("fname", (friend, name) -> friend.setFirstname(String.valueOf(name))),
    LASTNAME("lname", (friend, lname) -> friend.setLastname(String.valueOf(lname))),
    DATEOFBIRTH("dob", (friend, dob) -> friend.setDateOfBirth((LocalDate) dob)),
    PHONENUMBER("pno", (friend, pno) -> friend.setFirstname(String.valueOf(pno))),
    MOBILENUMBER("mno", (friend, mno) -> friend.setFirstname(String.valueOf(mno)));

    private String attributeName;

    private BiConsumer<Friend, Object> attributeSetter;

    public static Attribute getAttributeSetterByName(String attributeName) {
        return Arrays.stream(Attribute.values())
                .filter(attribute -> attribute.getAttributeName().equalsIgnoreCase(attributeName))
                .findFirst()
                .orElseThrow(() -> new RuntimeException(String.format("Invalid Attribute name - %s", attributeName)));
                //.orElse(null);
    }

    //Getter, Setter & Args Constructor (Use Lombok to reduce Boiler Plate code)
}

Update Logic 更新逻辑

    public void updateFriend(int id, String toChange, String newValue) {
        Attribute attribute = Attribute.getAttributeSetterByName(toChange);
        for (Friend friend : friends) {
            if (friend.getId() == id) {
                attribute.getAttributeSetter().accept(friend, newValue);
                break;
            }
        }
    }

You can use a java.util.function.Consumer<T> object to change an object inside your container where you have all the type safety you get. 您可以使用java.util.function.Consumer<T>对象来更改容器内具有所有类型安全性的对象。 Instead of having magic strings and string arguments for values, which might not be even for string fields, you can work directly on the objects type: 您可以直接对对象类型进行操作,而不是使用魔术字符串和值的字符串参数(甚至可能不包含字符串字段),也可以使用:

public void updateFriend(int id, Consumer<Friend> c) {
    // find the friend object
    Friend found = null;
    for (Friend f: this.friends) {
        if (f.getId() == id) {
            found = f;
            break;
        }
    }
    if (found == null) {
        throw new IllegalArgumentException("There is no friend object with the given id");
    }

    // use the friend object.
    c.accept(found);
}

You can use this method like this: 您可以这样使用此方法:

container.updateFriend(42, f -> f.setVorName("abc"));
container.updateFriend(9, f -> f.setAddress(some_address_object));

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

相关问题 查找存储在数组列表中的对象的平均值的最佳方法是什么? - What's the best way to find the average value of objects stored in an arraylist? 初始化ArrayList和HashMap的最佳方法是什么? - Best way to initialize ArrayList and HashMap? 创建 arraylist 哈希图的最佳方法 - Best way to create a hashmap of arraylist 打包/取消打包自定义对象的HashMap的最佳方法是什么? - What's the best approach to parcel/unparcel a HashMap of custom objects? 在哈希图中找到最大值的最佳方法<Arraylist,Arraylist> - Best way to find the largest value in a Hashmap<Arraylist,Arraylist> 比较具有多个列表属性的两个对象的最佳方法是什么 - What is the best way to compare two objects having multiple list attributes 如何将对象数组列表转换为哈希表,其中键和值是对象属性 - How to convert a object arraylist into a hashmap where key and value are the objects attributes 在Java中拥有巨大的ArrayList的最佳方法是什么? - What's the best way to have a gigantic ArrayList in Java? 访问存储在ArrayList中的对象的最佳方法? - Best way to access an object stored in an ArrayList? 为存储在HashMap中的arrayList的项目分配“等级” - Assigning a “rank” to a arrayList's items stored inside a HashMap
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM