середа, 13 березня 2019 р.

The frequency of unique elements in the list

Just a small reminder for myself. You have a class:
public class Entity {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

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

Then you create a test where you want to find out the frequency of every unique element (which is an instance of the class above) in the list. How can you do this? I am thinking to put all elements to HashSet to get distinct elements and then move through Set and call Collections.frequency. So the test could be like that:
import org.junit.Assert;
import org.junit.Test;
import java.util.*;

public class EntityTest {

    @Test
    public void testListToSet(){
        Entity entity1 = new Entity("Entity1", 1);
        Entity entity2 = new Entity("Entity2", 2);
        Entity entity3 = new Entity("Entity1", 1);
        Entity entity4 = new Entity("Entity2", 1);

        List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
        System.out.println("ArrayList: " + entityList);
        Assert.assertEquals(4, entityList.size());

        Set entityHashSet = new HashSet<>(entityList);
        System.out.println("HashSet: " + entityHashSet);
        Assert.assertEquals(3, entityHashSet.size());

        System.out.println("Frequency:");
        for (Entity entity : entityHashSet) {
            int frequency = Collections.frequency(entityList, entity);
            System.out.println(entity + " => " + frequency);
        }
    }

}

However, it will not work. Because you should override the equals and the hashCode methods. IDEA did it instead of me:
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Entity entity = (Entity) o;
    return count == entity.count &&
            Objects.equals(name, entity.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, count);
}

And after that the output will be next:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
HashSet: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity2', count=1}]
Frequency:
Entity{name='Entity1', count=1} => 2
Entity{name='Entity2', count=2} => 1
Entity{name='Entity2', count=1} => 1

If we need to store our list to TreeSet we should implement Comparable interface and override compareTo method. My approach:
public class Entity implements Comparable {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

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

    @Override
    public int compareTo(Entity o) {
        return Integer.compare(o.count, this.count);
    }
} 

And the test:
@Test 
public void testListToSet(){
    Entity entity1 = new Entity("Entity1", 1);
    Entity entity2 = new Entity("Entity2", 2);
    Entity entity3 = new Entity("Entity1", 1);
    Entity entity4 = new Entity("Entity2", 1);

    List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
    System.out.println("ArrayList: " + entityList);
    Assert.assertEquals(4, entityList.size());

    Set entityTreeSet = new TreeSet<>(entityList);
    System.out.println("TreeSet: " + entityTreeSet);
    Assert.assertEquals(2, entityTreeSet.size());
}

Output:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
TreeSet: [Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}]

Немає коментарів:

Дописати коментар