Steve Kamau
Steve Kamau

Reputation: 2785

How to sort an arrayList with string in descending order

I am getting json data as this:

[
  {
    "name": "A",
    "count": "2"
  },
  {
    "name": "B",
    "count": "1"
  },
  {
    "name": "A",
    "count": "3"
  },
  {
    "name": "C",
    "count": "10"
  },
  {
    "name": "B",
    "count": "2"
  }
]

So i iterate the data using a for loop, normal stuff. But i would like to end up with an arraylist like this:

C-->7

A-->5

B-->3

Notice that the the list is ordered from the highest to the lowest. What i have tried so far is:

//create my arraylists
    //has both name and count
     ArrayList<String>namesWithCountList = new ArrayList<>();
     //has only names 
     ArrayList<String>namesList = new ArrayList<>();

    //get json array..
    //iterate using for loop
     for (int i = 0; i < myJsonArray.length(); i++) {
      String nameStr = jsonObj.getString("name");
      int count = jsonObj.getInt("count");

      index = namesList.indexOf(name);//get index of the name

        if (index < 0) {
        // name doesnt exist in namesList, so we add it
       namesList.add(nameStr);
       namesWithCountList.add(nameStr+"-->"+count);
       }else{
        //name exists so we only add the count to existing list
       }

     }

I know i should use Comparator.sort() but i dont know how to get my list there because i have mixed both the name and count together like: C-->7

I have been stressing out on how the logic should look like, any help on this?

Upvotes: 0

Views: 752

Answers (3)

Dmitry Gorkovets
Dmitry Gorkovets

Reputation: 2276

If you want to sum all "A", all "B" etc. then following code may help. It uses Java 8 and Lombok library (for generating boilerplate code):

@NoArgsConstructor
@AllArgsConstructor
@Data
class Entity {
    private String name;
    private int count;
}

public class Main {

    public static void main(String[] args) {
        List<Entity> list = Arrays.asList(
                new Entity("A", 2),
                new Entity("B", 1),
                new Entity("A", 3),
                new Entity("C", 10),
                new Entity("B", 2));

        Map<String, Integer> grouped =
                list.stream().collect(Collectors.groupingBy(Entity::getName, Collectors.summingInt(Entity::getCount)));
        System.out.println(grouped);
    }
}

Result:

{A=5, B=3, C=10}

Upvotes: 1

Sourav Purakayastha
Sourav Purakayastha

Reputation: 775

Lets create an Entity class to hold your name and count mappings

import java.util.Comparator;

public class Entity implements Comparable {
private String name;
private int count;

public String getName() {
    return name;
}

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

public int getCount() {
    return count;
}

public void setCount(int count) {
    this.count = count;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + count;
    result = prime * result + ((name == null) ? 0 : name.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;
    Entity other = (Entity) obj;
    if (count != other.count)
        return false;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
}

public static Comparator<Entity> ArraylistComparator = new Comparator<Entity>() {

    public int compare(Entity e1, Entity e2) {
        int count1 = e1.getCount();
        int count2 = e2.getCount();

        // ascending order
        return e1.compareTo(e2);

    }
};

@Override
public int compareTo(Object o) {
    int compareCount = ((Entity) o).getCount();
    /* For Ascending order */
    return this.count - compareCount;

    /* For Descending order do like this */
    // return compareCount - this.count;
}

@Override
public String toString() {
    return "Entity [name=" + name + ", count=" + count + "]";
}

}

Then lets create a method in a separate class to populate the arrayList and call the comparator

import java.util.ArrayList;
import java.util.Collections;

public class ArraySort {

public static void main(String[] args) {
    ArrayList<Entity> arrayList = new ArrayList<Entity>();

    Entity entity1 = new Entity();
    entity1.setCount(2);
    entity1.setName("D");

    Entity entity2 = new Entity();
    entity2.setCount(10);
    entity2.setName("A");

    Entity entity3 = new Entity();
    entity3.setCount(5);
    entity3.setName("C");

    arrayList.add(entity1);
    arrayList.add(entity2);
    arrayList.add(entity3);

    System.out.println("Entity Count Sorting:");
    Collections.sort(arrayList, Entity.ArraylistComparator);

    for (Entity ent : arrayList) {
        System.out.println(ent);
    }
}

}

Output:

Entity [name=D, count=2]

Entity [name=C, count=5]

Entity [name=A, count=10]

Hope this helps!

Upvotes: 2

GhostCat
GhostCat

Reputation: 140407

You are getting your "mental" model wrong.

If your objects have a name and a count, then simply do not push them into strings like

"name-->count"

Instead: create your own custom class that holds these properties. And then you can create a (somehow) simpler Comparator for that class. That also simplifies the process of writing back JSON data if you intend to do that at some point.

If you insist on going on with your broken approach, then you have to create a Comparator that knows how to sort such kind of strings. In other words: your Comparator has to split such "n-->c" strings; and deduce name and count from it; to then do its job. But as said; you better give up on that idea.

As seriously: this is a super bad practice. Java is a strongly typed language; and coding multiple values into one flat string you are completely abandoning yourself from the "help" that the Java type system gives to you.

Upvotes: 6

Related Questions