Prevent duplicate entries in arraylist

2019-01-17 23:50发布

Say I create some object class like so

public class thing {
        private String name; 
        private Integer num;

        public oDetails (String a, Integer b) {
            name = a;
            num = b;
        }
...gets/ sets/ etc

Now I want to create an arraylist to hold a number of this object class like so.

ArrayList<thing> myList = new ArrayList<thing>;
thing first = new thing("Star Wars", 3);
thing second = new thing("Star Wars", 1);
myList.add(first);
myList.add(second);

I would like to include some sort of logic so that in this case...when we try and add object "second" rather than add a new object to the arrayList, we add second.getNum() to first.getNum(). So if you were to iterate through the ArrayList it would be

"Star Wars", 4

I am having trouble coming up with an elegant way of handling this. And as the arraylist grows, searching through it to determine if there are duplicate name items becomes cumbersome. Can anyone provide some guidance on this?

6条回答
地球回转人心会变
2楼-- · 2019-01-18 00:28

If you want to have a set of unique objects, use Set instead of List.

Also, if you want to define by yourself when objects are considered equal, consider overriding the equals and hashCode methods of the class.

查看更多
神经病院院长
3楼-- · 2019-01-18 00:30

You would have to create your own method to check to see if the the name field of class Thing was set to "Star Wars" then add to the corresponding num field of Class Thing, that is one possible solution.

Another solution is to use a Map with the name field as the key, and the num field as the value.

ex:

public class Thing
{
   private String name;
   private int    num;

   public Thing(String name, int num)
   {
       this.name = name;
       this.num  = num;
   } 
}

public class ThingMap
{
    Map<String, Integer> thingMap; 

    public ThingMap()
    {
       this.thingMap = new HashMap<>();
    }

    public void put(Thing t)
    {
       String  k = t.getName();
       Integer v = t.getNum();

       if(thingMap.get(k) == null) //no entry exists
       {
          thingMap.put(k, v);
       }
       else //entry exists
       {
          //add to the current value
          thingMap.put(k, thingMap.get(k) + v);
       }
    }

    public Integer get(String k)
    {
       return this.thingMap.get(k);
    }
}

public class TestThing
{
   public static void main(String[] args)
   {
      ThingMap tMap = new ThingMap();
      Thing a = new Thing("Star Wars", 3);
      Thing b = new Thing("Star Wars", 1);

      tMap.put(a);
      tMap.put(b);

      System.out.println("Current value: " + tMap.get(a.getName());
   }

}

Hope this helps.

查看更多
我只想做你的唯一
4楼-- · 2019-01-18 00:35

IMHO, it makes more sense to use a Map<String, Integer> instead of the ArrayList, or a Map<String, Thing> if you don't want to change your class.

查看更多
趁早两清
5楼-- · 2019-01-18 00:38
@Override
        protected Void doInBackground(Void... voids) {

            HttpHandler sh = new HttpHandler();

            String jsonStr = sh.makeServiceCall(Utils.SERVER_URL);

            Log.e(TAG, "Response from url: " + jsonStr);

            if (jsonStr != null) {
                try {
                    JSONObject jsonObject = new JSONObject(jsonStr);
                    JSONArray result = jsonObject.getJSONArray("result");

                    for (int i = 0; i < result.length(); i++) {

                        JSONObject data = result.getJSONObject(i);
                        String day = data.getString("day");

                        dataModels.add(day);

                        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
                        lhs.addAll(dataModels);
                        // Removing ArrayList elements
                        dataModels.clear();
                        dataModels.addAll(lhs);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
查看更多
来,给爷笑一个
6楼-- · 2019-01-18 00:47

You need to override the equals method and hashCode method in your class Thing in this way:

public class Thing {
        private String name;
        private Integer num;

        public Thing(String a, Integer b) {
            name = a;
            num = b;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setNum(Integer num) {
            this.num = num;
        }

        @Override
        public boolean equals(Object obj) {
            if(this == obj){
                return true;
            }

            if((obj == null) || (obj.getClass() != this.getClass())){
                return false;
            }

            Thing that = (Thing)obj;

            // Use the equality == operator to check if the argument is the reference to this object,
            // if yes. return true. This saves time when actual comparison is costly.
            return  num == that.num &&
                    (name == that.name || (name != null && name.equals(that.name)));

        }

        /**
         * This method returns the hash code value for the object on which this method is invoked.
         * This method returns the hash code value as an integer and is supported for the benefit of
         * hashing based collection classes such as Hashtable, HashMap, HashSet etc. This method must
         * be overridden in every class that overrides the equals method.
         *
         * @return
         */
        @Override
        public int hashCode() {
            int hash = 7;
            hash = 31 * hash + num;
            hash = 31 * hash + (null == name ? 0 : name.hashCode());
            return hash;
        }
    }

Then you could use it in this way:

ArrayList<Thing> myList = new ArrayList<>();

Thing first = new Thing("Star Wars", 3);

if(!myList.contains(first)){
   myList.add(first);
}

Thing second = new Thing("Star Wars", 1);

if(!myList.contains(second)){
   myList.add(second);
}

In my case I'm using LinkedHashSet to maintain the order of insertion and because I think is going to be more efficient. I didn't try this example with ArrayList.

For more information you can read from here: why I override equals and hashCode in this way

查看更多
叛逆
7楼-- · 2019-01-18 00:47

If you want to use List finally than Write your Comparator,

by writing Comparator you can create behaviour like set.

查看更多
登录 后发表回答