使用Stream和lambda

时间:2017-11-05 06:08:25

标签: java lambda java-stream

我有class A {int sNo; String name;}有效的构造函数。 我需要使用流API修剪名称并根据名称进行排序。

public class Test1 {
    public static void main(String[] args) {



    ArrayList<A> l = new ArrayList();
    l.add(new A(1, " 1name "));
    l.add(new A(7, " 3name "));
    l.add(new A(6, ""));
    l.add(new A(5, " 2name "));
    l.add(new A(4, " 5name "));
    l.add(new A(2, ""));

    List<String> i = l.stream()
            .filter(s -> !s.name.isEmpty())
            .map(s -> s.name.trim())
            .sorted()
            .collect(Collectors.toList());
    System.out.println(i); 
}

}

它只返回按排序顺序的名称

[, 1name, 2name, 3name, 5name]

但我需要整个对象。

我知道s -> s.name.trim()是仅存储名称的原因,

如何对特定字段进行操作但存储整个对象。

3 个答案:

答案 0 :(得分:2)

只是为了好玩,不是因为它特别好或甚至推荐。也可以使用匿名对象实现这一点:

    List<A> i = l.stream()
            .filter(s -> !s.name.isEmpty())
            .map(s -> new Object() {A a = s; String name = s.name.trim();})
            .sorted(Comparator.comparing(o -> o.name))
            .map(o -> o.a)
            .collect(Collectors.toList());

并非每个编译器都会对此感到高兴(javac会),但它是有效的Java代码。

答案 1 :(得分:1)

使用map函数时,您将所有对象转换为字符串,因此不是使用map,而是使用每个对象来转换对象内部的字符串,但不返回字符串列表:

 class A {
 int sNo; 
 String name;

 public int getName(){ return name}



 public void setName(String name){ this.name = name;}

  }

i.forEach(s -> s.setName(s.getName().trim()));

List<A> i = l.stream()
        .filter(s -> !s.name.isEmpty())       
        .sorted(Comparator.comparing(a -> a.name))
        .collect(Collectors.toList());

答案 2 :(得分:1)

  

它只返回排序顺序的名称[...],但我需要整个对象。

.map(s -> s.name.trim())步骤会将您的A信息流转换为String信息流。这就是你留下字符串而不是整个对象的原因。

如果您想要一个排序的对象列表,那么结果应该在List<A>而不是List<String>

要按字段对对象列表进行排序,您可以将Comparator传递给sorted

List<A> result = l.stream()
    .filter(s -> !s.name.isEmpty())
    .map(s -> new A(s.sNo, s.name.trim()))
    .sorted(Comparator.comparing(a -> a.name))
    .collect(Collectors.toList());

如果您不想创建带有修剪名称的new A, 但是想要修改原始对象(虽然我很怀疑), 您可以使用map替换peek步骤并修改对象:

.peek(s -> s.name = s.name.trim())

但请注意,正如@Mustafa指出的那样,peek仅用于调试。事实上,如果你想修改底层对象,那么在与过滤和排序分开的步骤中,最好是这样做, 因为它无论如何都是一个逻辑上无关的步骤(它看起来像数据清理)。 该步骤可以使用forEach实现。

如果你实际上不需要修剪名称(感谢@Andreas提示), 仅用于分类, 然后你可以完全放弃map步骤, 并像这样写sorted步骤:

.sorted(Comparator.comparing(a -> a.name.trim()))