0

I am getting duplicate entries into ListView using ArrayList to populate and HashSet to remove duplicate elements, but still getting duplicate values like this:

Delhi
Mumbai
Delhi
Mumbai

Here is my code which i am using to parse JSON data into List and to remove duplicate entries

MainActivity.java:

public class MainActivity extends Activity {

    ArrayList<Destination> destinationArrayList;    
    MainAdapter adapter;
    Destination destination;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        destinationArrayList = new ArrayList<Destination>();

        new JSONAsyncTask().execute("my api link");

        Set<Destination> hashset = new HashSet<>(); 
        hashset.addAll(destinationArrayList); 
        destinationArrayList.clear(); 
        destinationArrayList.addAll(hashset);

        ListView listview = (ListView)findViewById(R.id.list);
        adapter = new MainAdapter(getApplicationContext(), R.layout.row, destinationArrayList);

        listview.setAdapter(adapter);

        listview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                    long id) {
                // TODO Auto-generated method stub
                Toast.makeText(getApplicationContext(), destinationArrayList.get(position).getTitle().toString(), Toast.LENGTH_LONG).show();                
            }
        });

    }


    class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {

        ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setMessage("Loading, please wait");
            dialog.show();
            dialog.setCancelable(false);
        }

        @Override
        protected Boolean doInBackground(String... urls) {
            try {

                //------------------>>
                HttpGet httppost = new HttpGet(urls[0]);
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = httpclient.execute(httppost);

                // StatusLine stat = response.getStatusLine();
                int status = response.getStatusLine().getStatusCode();

                if (status == 200) {
                    HttpEntity entity = response.getEntity();
                    String data = EntityUtils.toString(entity);


                    JSONObject jsono = new JSONObject(data);
                    JSONArray jarray = jsono.getJSONArray("data");

                    for (int i = 0; i < jarray.length(); i++) {
                        JSONObject object = jarray.getJSONObject(i);

                        destination = new Destination();

                        destination.setCity(object.getString("city"));

                        destinationArrayList.add(destination);

                    }
                    return true;
                }

                //------------------>>

            } catch (ParseException e1) {
                e1.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return false;
        }

        protected void onPostExecute(Boolean result) {
            dialog.cancel();
            adapter.notifyDataSetChanged();
            if(result == false)
                Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();

        }
    }

}

And when i use this, even not getting single record into ListView:

destinationArrayList = new ArrayList<Destination>();

        new JSONAsyncTask().execute("my api url");

        System.out.println("size of Arraylist with duplicates: " + destinationArrayList.size());

        System.out.println(destinationArrayList);

        HashSet<Destination> listToSet = new HashSet<Destination>(destinationArrayList);

        ArrayList<Destination> listWithoutDuplicates = new ArrayList<Destination>(listToSet);
        System.out.println("size of ArrayList without duplicates: " + listToSet.size());

        System.out.println(listWithoutDuplicates);

Destination.java

public class Destination {

    private String city;
    ..............

    public Destination() {
        // TODO Auto-generated constructor stub
    }

    public Destination(String city) {
        super();
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

}
Oreo
  • 2,586
  • 8
  • 38
  • 63

4 Answers4

3

You are putting the Custom objects to the HashSet so it is not eliminating duplicates. You need to override the equals and hashCode for the Destination object. Then it works fine.

class Destination {

    private String city;

    public Destination() {
        // TODO Auto-generated constructor stub
    }

    public Destination(String city) {
        super();
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Destination that = (Destination) o;

        if (city != null ? !city.equals(that.city) : that.city != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return city != null ? city.hashCode() : 0;
    }
}

place this code in on postExecute() method in the AsynTask then it shows the all the elements in the list.

 Set<Destination> hashset = new HashSet<>(); 
        hashset.addAll(destinationArrayList); 
        destinationArrayList.clear(); 
        destinationArrayList.addAll(hashset);

        ListView listview = (ListView)findViewById(R.id.list);
        adapter = new MainAdapter(getApplicationContext(), R.layout.row, destinationArrayList);

        listview.setAdapter(adapter);
Krishna V
  • 1,801
  • 1
  • 14
  • 16
0

The de-duplication using the Set is not working since, given your current Destination class definition, instances of Destination that have the same city value are not considered equal.

Try overriding .equals in your Destination class....

Community
  • 1
  • 1
Tom Mac
  • 9,693
  • 3
  • 25
  • 35
0

I would bet that the hash set could not recognize two pairs of Destination objects as equal no matter that they have only one property City.

To compare two objects you would need to override the super method equals and as well your object is being used into a hash table, you would need also to override hashCode

There are some proven methods which will avoid collisions on hashes that you could use in hashCode. One of them is Best implementation for hashCode method

Community
  • 1
  • 1
Royal Bg
  • 6,988
  • 1
  • 18
  • 24
0

Your Destination class should have equals() and hashCode() methods to eliminate duplicate records aganist to city. The following code which include the methods can solve your problem :

public class Destination {

    private String city;
    ..............

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((city == null) ? 0 : city.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Destination other = (Destination) obj;
        if (city == null) {
            if (other.city != null)
                return false;
        } else if (!city.equals(other.city))
            return false;
        return true;
    }
}
Erol Ozcan
  • 31
  • 3