Collectors.toMap在不使用值的对象的属性上编写合并函数

时间:2019-06-12 12:08:34

标签: java java-8 java-stream

我正在使用Java-8流从Map<String,String>创建一个List<Person>

persons.stream()
       .collect(Collectors.toMap(Person::getNationality, Person::getName, (name1, name2) -> name1)

但是在以上情况下,我想通过使用人的年龄来解决名字冲突。有什么办法可以绕行(age1, age2) -> // if age1 is greater than age2 return name1, else return name2传递合并功能吗?

3 个答案:

答案 0 :(得分:8)

要根据年龄选择一个人,您需要public class NetworkUtils { public static String getJSONFromAPI (String url){ String output = ""; try { URL apiEnd = new URL(url); int responseCode; HttpURLConnection connection; InputStream is; connection = (HttpURLConnection) apiEnd.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(15000); connection.setConnectTimeout(15000); connection.connect(); responseCode = connection.getResponseCode(); if(responseCode < HttpURLConnection.HTTP_BAD_REQUEST){ is = connection.getInputStream(); }else { is = connection.getErrorStream(); } output = convertISToString(is); is.close(); connection.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return output; } private static String convertISToString(InputStream is){ StringBuffer buffer = new StringBuffer(); try { BufferedReader br; String row; br = new BufferedReader(new InputStreamReader(is)); while ((row = br.readLine())!= null){ buffer.append(row); } br.close(); } catch (IOException e) { e.printStackTrace(); } return buffer.toString(); } } 实例来查询年龄。将Person映射到纯名称Person后,您将无法重新构成信息。

因此,您必须首先收集人员,以便能够选择最老的人员,然后将其映射到其姓名:

String

答案 1 :(得分:3)

如果您不想使用助手数据结构,则可以先保留“个人”信息并基于该信息执行合并,然后再应用映射:

public void test() {
    final List<Person> persons = new ArrayList<>();

    final BinaryOperator<Person> mergeFunction =
        (lhs, rhs) -> lhs.getAge() > rhs.getAge() ? lhs : rhs;

    final Function<Person, String> mapFunction = Person::getName;

    final Map<String, String> personNamesByNation =
        persons.stream()
            .collect(
                Collectors.groupingBy(Person::getNation, // KeyMapper Person.getNation: Map<String, List<Person>>
                    Collectors.collectingAndThen(
                        Collectors.collectingAndThen(
                            Collectors.reducing(mergeFunction), // Merge Persons into single value via merge function: Map<String, Optional<Person>>
                            Optional::get), // unwrap value: Map<String, Person>
                        mapFunction))); // apply map function afterwards: Map<String, String>
}

答案 2 :(得分:1)

按年龄排序信息流的元素,然后先选择:

persons.stream()
       .sorted(Comparator.comparing(Person::getAge).reversed())
       .collect(Collectors.toMap(Person::getNationality, Person::getName, (n1, n2) -> n1));