我有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()
是仅存储名称的原因,
如何对特定字段进行操作但存储整个对象。
答案 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()))