1

I have a List<String> which contains names I want to convert that list to an other list of unique names I found a way that works well which is:

public class Main {

  public Main() {
    List<String> nameList = new ArrayList<>();

    nameList.add("Ali");
    nameList.add("Al");
    nameList.add("Ali");
    nameList.add("Al");
    nameList.add("Ai");
    nameList.add("li");
    nameList.add("li");
    nameList.add("Ai");
    System.out.print("All names are: ");
    for (String string : nameList) {
      System.out.print(string + ", ");
    }
    System.out.println("");

    System.out.print("Unique names are: ");

    for (String string : convertToUniqueList(nameList)) {
      System.out.print(string + ", ");
    }

  }

  public List<String> convertToUniqueList(List<String> listInts) {
    List<String> listDistinctInts = new ArrayList<>(listInts.size());
    for (String i : listInts) {
      if (!listDistinctInts.contains(i)) {
        listDistinctInts.add(i);
      }
    }
    return listDistinctInts;
  }

  public static void main(String[] args) {
    new Main();
  }

}

all things are working very well and I'm getting desired results, but I want to implement the same logic as above to following scenario where I have:

  @Data // lombok annotation
  public class Foo {
    String name;
    int age;    
    List<Bar> barList = new ArrayList<>();    
  }

  @Data // lombok annotation
  public class Bar {
    String bloodGroup;
    String dayOfPassing;
  }

I want to get a list with unique day names from misc list in Main.java I tried:

public class Main {

  public Main() {
    Foo foo1 = new Foo();

    foo1.setName("Foo One");
    foo1.setAge(21);

    List<Bar> barList = new ArrayList<>();

    Bar bar1 = new Bar();
    bar1.setBloodGroup("O +ve");
    bar1.setDayOfPassing("Wednesday");

    Bar bar2 = new Bar();
    bar2.setBloodGroup("O +ve");
    bar2.setDayOfPassing("Wednesday");

    Bar bar3 = new Bar();
    bar3.setBloodGroup("O +ve");
    bar3.setDayOfPassing("Thursday");

    Bar bar4 = new Bar();
    bar4.setBloodGroup("O -ve");
    bar4.setDayOfPassing("Friday");

    barList.add(bar1);
    barList.add(bar2);
    barList.add(bar3);
    barList.add(bar4);

    System.out.print("All Bars with all days are: ");
    for (Bar bar : barList) {
      System.out.print(bar.dayOfPassing + ", ");
    }
    System.out.println("");

    System.out.print("Bars with Unique days are: ");
    int count = 0;
    for (Bar bar : getBarsWithUniqueDays(barList, count)) {
      System.out.print(bar.dayOfPassing + ", ");
      count++;
    }

  }

  public List<Bar> getBarsWithUniqueDays(List<Bar> barList, int count) {
    List<Bar> listDistinctBars = new ArrayList<>(barList.size());

    for (Bar bar : barList) {
      if (!listDistinctBars.get(count).getDayOfPassing().contains(bar.dayOfPassing)) {
        listDistinctBars.add(bar);
      }
      count++;
    }
    return listDistinctBars;
  }

  public static void main(String[] args) {
    new Main();
  }
}

with that code above I'm getting Exception:

All Bars with all days are: Wednesday, Wednesday, Thursday, Friday, 
Bars with Unique days are: Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at Main.getBarsWithUniqueDays(Main.java:124)
    at Main.<init>(Main.java:113)
    at Main.main(Main.java:133)

I have searched and tried a lot but in vain, any solutions to this problem...

Arshad Ali
  • 3,082
  • 12
  • 56
  • 99

4 Answers4

1
    Map<String, Bar> map = new LinkedHashMap<>();
    for (Bar ays : barList) {
        map.put(ays.dayOfPassing, ays);
    }
    barList.clear();
    barList.addAll(map.values());


    for (Bar ays : barList) {

        System.out.println("Unique names are: "+ays.dayOfPassing);
    }
sasikumar
  • 12,540
  • 3
  • 28
  • 48
0

You are getting an IndexOutOfBoundsException because your code is invoking listDistinctBars.get(count) on an empty ArrayList with count equal to 0. However, to properly deduplicate your objects, you should look into java.util.Set.

GJL
  • 143
  • 8
  • I have tried that as well but unfortunately that technique requires to override `hashCode()` and when I do so ultimately I get some duplicate values.... – Arshad Ali Nov 21 '19 at 12:38
0

Best pracite is to use HashSet or LinkedHashSet (when order is important) (implementation of Set) for unique elements.

All u need is convert your ArrayList to HashSet and after that override equals&hashcode of your class Bar. Here is example of overriding EXAMPLE

  • I have tried that as well but unfortunately that technique requires to override hashCode() and when I do so ultimately I get some duplicate values.... – Arshad Ali Nov 21 '19 at 12:42
  • it means that u werent correct in overriding. Here is working example of overriding in my answer. – Eugene Borisov Nov 21 '19 at 12:45
0

I found a way that works well which is:

I don't thing so, Instead you can just use a Set

public Set<String> convertToUniqueList(List<String> listInts) {
    return new HashSet<>(listInts);
}

for the second problem, you can use stream its more helpful based on the Distinct by property your solution can be :

public List<Bar> getBarsWithUniqueDays(List<Bar> barList) {
    return barList.stream().filter(distinctByKey(Bar::getDayOfPassing))
            .collect(Collectors.toList());

}

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140