Niranga Sandaruwan
Niranga Sandaruwan

Reputation: 711

Java 8 streams maintain specific map key order return from group by operation

I have a list with collections of TitleIsbnBean objects. I wrote the following code snippet to group by this collection by learning area type as below.

titleListByLearningArea = nonPackageIsbnList.stream()
      .collect(groupingBy(TitleIsbnBean::getKeylearningarea,
                          LinkedHashMap::new,Collectors.toList())

              );

but I want to preserve the following specific order in the map return from the above stream.

titleListByLearningArea.put("Commerce", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("English", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Health & PE", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Humanities", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Mathematics", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Music & the Arts", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Science", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Others", new ArrayList<TitleIsbnBean>() {});

but I'm getting a different order once I group by the collections using streams. How can I maintain a specific order when stream group by operation using.

class TitleIsbnBean {

  private String titleName;
  private String isbn;
  private int status;
  private String keylearningarea;

  public TitleIsbnBean(String titleName, String isbn, int status, String keylearningarea){
    super();
    this.titleName = titleName;
    this.isbn = isbn;
    this.status = status;
    this.setKeylearningarea(keylearningarea);
  }

}

ArrayList<TitleIsbnBean> nonPackageIsbnList = new ArrayList<>();
Map<String,List<TitleIsbnBean>> titleListByLearningArea = new LinkedHashMap<>();

titleListByLearningArea.put("Commerce", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("English", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Health & PE", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Humanities", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Mathematics", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Music & the Arts", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Science", new ArrayList<TitleIsbnBean>() {});
titleListByLearningArea.put("Others", new ArrayList<TitleIsbnBean>() {});

titleListByLearningArea = nonPackageIsbnList.stream()
.collect(Collectors.groupingBy(TitleIsbnBean::getKeylearningarea,
                                LinkedHashMap::new,Collectors.toList()));

Upvotes: 1

Views: 678

Answers (2)

Eklavya
Eklavya

Reputation: 18420

First sort the list using Comparator with your desired order then collect the list in group.

List<String> orderKeys = List.of("Commerce", "English", "Health & PE", "Humanities",
        "Mathematics", "Music & the Arts", "Science", "Others");

Map<String, List<TitleIsbnBean>> titleListByLearningArea = nonPackageIsbnList.stream()
                   .sorted(Comparator.comparingInt(t -> orderKeys.indexOf(t.getKeylearningarea())))
                   .collect(Collectors.groupingBy(TitleIsbnBean::getKeylearningarea,LinkedHashMap::new,Collectors.toList()));

Upvotes: 1

Naman
Naman

Reputation: 31868

Considering you need a desired order of keys for the Map you are collecting in, you can collect to a TreeMap with a Comparator based on index specified such as:

Collection<TitleIsbnBean> nonPackageIsbnList = .... //initialisation
List<String> orderedKeys = List.of("Commerce", "English", "Health & PE", "Humanities",
        "Mathematics", "Music & the Arts", "Science", "Others");

Map<String, List<TitleIsbnBean>> titleListByLearningArea = nonPackageIsbnList.stream()
        .collect(Collectors.groupingBy(TitleIsbnBean::getKeylearningarea,
                () -> new TreeMap<>(Comparator.comparingInt(orderedKeys::indexOf)),
                Collectors.toList()));

Upvotes: 3

Related Questions