可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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:
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.
回答4:
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
回答5:
If you want to use List finally than Write your Comparator
,
by writing Comparator you can create behaviour like set.
回答6:
@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;
}