bautista
bautista

Reputation: 794

Select distinct fields of an ArrayList of Class X

I have an ArrayList of Class X.

ArrayList<X> items = new ArrayList();

Class X contains multiple fields, all of the type string. (id, description, brand, ...)

So what do i do if i wanna get an ArrayList of this Class which only contains distinct values for a given field?

In practice:

How can I get an ArrayList of Class X which contains all the brands but no duplicates? (get all the brands in items but no brand twice)

Or is there any better/more efficient way to only get a list of the brands?

\e: i dont use Java8.

Hope this isn't too confusing.

Upvotes: 0

Views: 1254

Answers (3)

Eritrean
Eritrean

Reputation: 16498

 items.stream()
            .collect(Collectors.groupingBy(X::getBrand))   // group your items by brand
            .values().stream()                            // stream map values
            .map(e->e.get(0))                            // for each brand get first element in brand list 
            .collect(Collectors.toList());

If you cann't use java8 / streams

    Map<String,List<X>> map = new HashMap<>();
    for(X item : items){
        if(!map.containsKey(item.getBrand())){
            map.put(item.getBrand(), new ArrayList<>());
        }else{
            map.get(item.getBrand()).add(item);
        }
    }
    List<X> result = new ArrayList<>();
    for(Map.Entry<String,List<X>> e : map.entrySet()){
        result.add(e.getValue().get(0));
    }

Upvotes: 1

Syed Khalid Ahmed
Syed Khalid Ahmed

Reputation: 3232

1) Use a utility method distinctbykey in filter if you want to get unique result on some field.

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> map = new ConcurrentHashMap<>();
    return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
  }

ArrayList<X> items = new ArrayList();
items = items
  .stream()
  .filter( distinctByKey(x -> x.uniqueFiled()) ) // pass field of X object on basis of you want unique objects
  .collect(Collectors.toList());

2) There is another way to get no duplication in list. Override equals and hash function of X class in which you have to compare Brand field and then use distinct method of stream it will return distinct objects list by calling of your equals and hash function.

ArrayList<X> items = new ArrayList();
items = items
  .stream()
  .distinct()
  .collect(Collectors.toList());

3) If you implement equals and hash functions. then simply create a Set from List. Set has unique elements and ten again create List from that Set.

ArrayList<X> items = new ArrayList();
Set<X> set = new HashSet<X>(items); // Now set has unique elements
items = set.stream().collect(Collectors.toList()); // list have unique elemets too

Upvotes: 0

spi
spi

Reputation: 1735

Use a java.util.Set which by definition, does not allow duplicated values.

Set<String> s = new HashSet<>();
for(X x : items) {
    s.add(x.getField());
}

// "s" now contains all distinct "field"

there should be a version of this code using lambdas and streams. But IMO such simple code does not require it

Upvotes: 0

Related Questions