<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"(11I10I24) 活 动 中 心" <1015770492@qq.com><br><b>To: </b>"core-libs-dev" <core-libs-dev@openjdk.org><br><b>Sent: </b>Saturday, August 6, 2022 11:49:18 AM<br><b>Subject: </b>More elegant multi-condition groupby. #9719<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div>Hi, team</div><br><div>I have two suggestions</div><br><div>Firstly:</div><br><div><code class="notranslate" style="box-sizing: border-box; padding: 0.2em 0.4em; margin: 0px; background-color: ; border-radius: 6px;"><font face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" color="#24292f">If we can provide a new API for grouping (</font></code><span style="background-color: rgba(175, 184, 193, 0.2); color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 11.9px;">java.util.stream.Collectors </span><span style="color: rgb(36, 41, 47); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; background-color: ;">)</span></div><div><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;">such as:</span></font></div><div><code class="notranslate" style="box-sizing: border-box; padding: 0.2em 0.4em; margin: 0px; background-color: ; border-radius: 6px;"><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;">userList.stream().collect(Collectors.groupingBy(User::getName, User::getCity))</span></font></code></div><div><code class="notranslate" style="box-sizing: border-box; padding: 0.2em 0.4em; margin: 0px; background-color: ; border-radius: 6px; font-size: 12px;"><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f">userList.stream().collect(Collectors.groupingBy("-", User::getName, User::getCity, User::getId));// key is "name-city", value is </font></code><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;">List after being grouped</span></font></div><br><div><span style="color: rgb(36, 41, 47); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";">It helps us to do grouping with less code. and </span><font face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" color="#24292f">It looks cooler for lambda.</font></div><div><font face="-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" color="#24292f"><br></font></div><div><span style="color: rgb(36, 41, 47); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";">And </span><span style="color: rgb(36, 41, 47); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";">I've provided a simple demo. </span></div><div>demo: https://github.com/1015770492/CollectorsDemo/blob/master/src/main/java/com/example/demo/MultiGroupByDemo.java</div><div>issue: https://github.com/openjdk/jdk/pull/9719</div><br><div>Secondly:</div><br><div>similarly, if we can provide new api for sort with stream. </div><div>It can be:</div><div><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">userList.stream().sorted(User::getAge) </span></div><div><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">or </span><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">userList.stream().sorted(User::getName)  </span></div><div><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">or </span><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">userList.stream().sorted(User::getName, User::getAge)</span></div><br><div><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">userList.stream().sorted(User::getAge) age is a Integer or int type ,it is </span><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;">Comparable, So if we can use the Function reference implements sort.</span></font></div><br><div>String implements the <span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">Comparable Interface but we do not use the </span><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;">features.</span></font></div><br><br><div><div><span style="color: rgb(36, 41, 47); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px;">userList.stream().sorted(User::getCity, User::getName)</span></div></div><div>multi-condition sort we can transfor to String sort. </div></blockquote><div><br></div><div>Hi !<br data-mce-bogus="1"></div><div>we usually add additional APIs because it's cooler :)<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>If i understand you correctly, you are saying that from a user POV dealing with composite keys for grouping or sorting could be improved.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>I really do not like you first proposal because you are introducing a String where you could introduce a real object (the composite key), here string acting as a cheaper inferior object.<br data-mce-bogus="1"></div><div>Using a record seems to be a better idea (technically what we want here is tuples but records is good enough)<br data-mce-bogus="1"></div><div>  record CompositeKey(String name, int age) { }<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>  so you can write<br data-mce-bogus="1"></div><div>   list.stream().collect(groupingBy(user -> new CompositeKey(user.getName, user.getAge())))<br data-mce-bogus="1"></div><div> </div><div>  and with a static method in CompositeKey<br data-mce-bogus="1"></div><div>   record CompositeKey(String name, int age) {</div><div>     static CompositeKey fromUser(User user) { return new CompositeKey(user.getName, user.getAge()); }<br data-mce-bogus="1"></div><div>   }<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>  it can be simplified to<br data-mce-bogus="1"></div><div>   list.stream().collect(groupingBy(CompositeKey::fromUser))<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>For sorting, it's a different, the API you propose has already have been proposed and rejected during the development of Java 8<br></div><div>Comparing using Integer instead of int is really slow, so we do not want users to be forced to box things.<br data-mce-bogus="1"></div><div>The API you propose requires the return type of User::getCity and the return type User::getAge to be inferred as the same type variable, sadly it means boxing, so it's not a good API.</div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><br><div>best regards</div><div>Yu, Jinhua</div><div>1015770492@qq.com</div><br><div><font face="ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace" color="#24292f"><span style="font-size: 12px;"><br></span></font></div><div><br></div></blockquote><div>regards,<br></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div></div></div></body></html>