6

我有一系列格式如下的输入字符串:

typeA:code1,
typeA:code2,
typeA:code3,
typeB:code4,
typeB:code5,
typeB:code6,
typeC:code7,
...

我需要得到一个Map<String, List<String>>具有以下结构的:

typeA, [code1, code2, code3]
typeB, [code4, code5, code6]
typeC, [code7, code8, ...]

问题是,要生成每种类型,我需要在每个输入字符串上调用这样的函数:

public static String getType(String code)
{
  return code.split(":")[0];  // yes this is horrible code, it's just for the example, honestly
}

我非常有信心 Streams 和 Collectors 可以做到这一点,但我正在努力获得正确的咒语来实现它。

4

4 回答 4

8

这是一种方法(假设类名为A):

Map<String, List<String>> result = Stream.of(input)
                          .collect(groupingBy(A::getType, mapping(A::getValue, toList())));

如果要对输出进行排序,可以使用 TreeMap 而不是默认的 HashMap:

.collect(groupingBy(A::getType, TreeMap::new, mapping(A::getValue, toList())));

完整示例:

public static void main(String[] args) {
  String input[] = ("typeA:code1," +
                "typeA:code2," +
                "typeA:code3," +
                "typeB:code4," +
                "typeB:code5," +
                "typeB:code6," +
                "typeC:code7").split(",");

  Map<String, List<String>> result = Stream.of(input)
                    .collect(groupingBy(A::getType, mapping(A::getValue, toList())));
  System.out.println(result);
}

public static String getType(String code) {
  return code.split(":")[0];
}
public static String getValue(String code) {
  return code.split(":")[1];
}
于 2015-08-28T14:10:27.460 回答
8

如果您考虑省略的内容,代码会变得很简单,您还需要拆分字符串的第二部分:

Map<String, List<String>> result = Stream.of(input).map(s->s.split(":", 2))
    .collect(groupingBy(a->a[0], mapping(a->a[1], toList())));

(假设你有一个import static java.util.stream.Collectors.*;

将 a 拆分为数组并没有错,String对于使用单个简单字符而不是复杂的正则表达式进行拆分的常见情况,实现甚至具有“快速路径”。

于 2015-08-28T14:13:55.617 回答
2

虽然我的速度太慢,但这里有一个MCVE,展示了如何使用Collectors#groupingBy.

定义“分类器”和“映射器”显然有不同的选择。在这里,我只是String#substring用来查找":".

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class GroupingBySubstringsTest
{
    public static void main(String[] args)
    {
        List<String> strings = new ArrayList<String>();
        strings.add("typeA:code1");
        strings.add("typeA:code2");
        strings.add("typeA:code3");
        strings.add("typeB:code4");
        strings.add("typeB:code5");
        strings.add("typeB:code6");
        strings.add("typeC:code7");

        Map<String, List<String>> result = strings.stream().collect(
            groupingBy(s -> s.substring(0, s.indexOf(":")), 
                mapping(s -> s.substring(s.indexOf(":")+1), toList())));

        for (Entry<String, List<String>> entry : result.entrySet())
        {
            System.out.println(entry);
        }
    }
}
于 2015-08-28T14:25:09.877 回答
0

考虑学生班:

public Student(String name, Address add) {
    super();
    this.name = name;
    this.add = add;
}
private String name;
private Address add;
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public Address getAdd() {
    return add;
}
public void setAdd(Address add) {
    this.add = add;
}

}

和地址类:

class Address{

public Address(String city, String state) {
    super();
    this.city = city;
    State = state;
}
private String city;
private String State;
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getState() {
    return State;
}
public void setState(String state) {
    State = state;
}

}

现在,如果我想根据属于 Address 类的 City & State 对 Student 进行分组:

Student s1 = new Student("Rohit", new Address("Mumbai", "MH"));
    Student s2 = new Student("Sudeep", new Address("Mumbai", "MH"));
    Student s3 = new Student("Amit", new Address("Pune", "MH"));
    Student s4 = new Student("Rahul", new Address("Blore", "KR"));
    Student s5 = new Student("Vishal", new Address("Blore", "KR"));
    
    List<Student> st =  Arrays.asList(s1,s2,s3,s4,s5);
    
    Function<Student, String> compositeKey = studRecord -> studRecord.getAdd().getCity()+":"+ studRecord.getAdd().getState();
    
    Map<String, List<Student>> groupedStudent =  st.stream()
            .collect(Collectors.groupingBy(compositeKey));
于 2020-07-22T22:24:36.080 回答