Java 8 爪哇8流及;格式化程序或字符串::格式

Java 8 爪哇8流及;格式化程序或字符串::格式,java-8,java-stream,formatter,Java 8,Java Stream,Formatter,如何使用流格式化字符串,而不使用lambda?我一直在查看格式化程序,但找不到任何只需要一个字符串的方法。。。所以我可以做: Set<String> imported = new HashSet<>(); extendedModels.stream().filter((x)->imported.add(x)) .map(new Formatter("import {%1$s} from './%1$s';\n")::format); 与问题无关的详情: 我

如何使用流格式化字符串,而不使用lambda?我一直在查看格式化程序,但找不到任何只需要一个字符串的方法。。。所以我可以做:

Set<String> imported = new HashSet<>();
extendedModels.stream().filter((x)->imported.add(x))
    .map(new Formatter("import {%1$s} from './%1$s';\n")::format);
与问题无关的详情: 我试图遍历一个字符串列表,将它们简化为唯一的*)字符串,然后在格式化字符串中使用它们,最终将它们写入
编写器
。以下是我现在拥有的:

这会起作用,但我必须在
forEach
中处理
IOException

extendedModels.stream().filter(imported::add)
.map((x)->{return String.format("import {%1$s} from './%1$s';\n", x);})
.forEach(tsWriter::write);
所以现在我用这个:

tsWriter.write(
    extendedModels.stream()
        .filter(imported::add)
        .map((x)->{return String.format("import {%1$s} from './%1$s';\n", x);})
        .collect(Collectors.joining())
);

*)唯一性是跨多个集合的,而不仅仅是
extendedModels
,因此我不想使用某种
unique
stream util。

避免使用lambda表达式和仅使用方法引用,您需要将格式化部分提取到静态或实例方法,并使用方法引用表达式引用它:

static String formatImportStatement(String imp) {
    return String.format("import {%1$s} from './%1$s';\n", imp);
}
然后
.map(YourClass::formatImportStatement)
。或者您也可以将labmda本身提取到如下变量:

Function<String, String> importFormatter = 
    (s) ->  String.format("import {%1$s} from './%1$s';\n", s);
函数导入格式=
(s) ->String.format(“从“/%1$s';\n”,s导入{%1$s}”);
然后直接使用它:
.map(导入格式)


关于例外情况:

您可以使用委托
编写器
包装器,该包装器软化(将选中的异常转换为未选中的异常)并从其方法签名中取消声明选中的
IOException
-s,然后将其与
.forEach(softeningWriter::write)
一起使用

您还可以使用lambda包装器工厂来包装lambda,以使用
.forEach(rethrowConsumer(tsWriter::write))
模式来软化异常,例如这里的
LambdaExceptionUtil

如果您不介意先使用
Collectors.joining()
将导入语句收集到
String
,那么第三种解决方案也可以工作


不幸的是,您需要绕过检查过的异常(至少在今天的Java8中是这样)。也许Java的未来版本会对这个遗留问题做些什么,但据我所知,这并不一定会发生。

请注意,虽然
.filter(imported::add)
看起来像是一个聪明的把戏,但它是一种不受鼓励的技术,因为它创建了一个有状态谓词。如果您只需要唯一性,只需使用
.distinct()
。如果以后需要导入
,请使用直接的收集操作创建它,即
imported=newhashset(extendedModels)
并在
集合上进行流式处理

因此,如果您的
Writer
要写入一个文件或任何路径,有一个
文件系统
实现,一个简单的解决方案是

Set<String> imported = new HashSet<>(extendedModels);
Files.write(path, () -> imported.stream()
    .<CharSequence>map(x->String.format("import {%1$s} from './%1$s';\n", x)).iterator());
如果没有
路径
,即无法避免使用预定义的
编写器
,则可以使用
格式化程序
,但必须注意不要遗漏异常:

Formatter f=new Formatter(tsWriter);
extendedModels.stream().distinct().forEachOrdered(
    x -> f.format("import {%1$s} from './%1$s';\n", x));
f.flush();
if(f.ioException()!=null) throw f.ioException();

无法向方法引用提供绑定参数,但由于标记
String
format
和字符串文本是不可避免的,因此也没有多少潜在的保存空间。

您想实现什么?是否在列表中收集一些导入语句字符串?将它们输出到一个流?哦,你想用方法引用来做任何事情,而不需要lambda表达式?有点像。为了简洁易读。这是可行的,但我找不到用于此的类。好的,谢谢,但问题是关于格式-如何避免lambda可读性较差的表达式,并使用新的格式化程序(“%s…”::Formatter是的,当然,您也可以使用
Formatter
,但是您需要手动查询格式化程序以查找
IOException
-s,因为
Formatter
为您吞咽IOException。
String.format
也“吞咽
IOException
”或者您必须添加
try catch
块吗?@Holger没有声明抛出
IOException
,因此不需要捕获它。
Formatter.format
也是如此。这就是您的语句“那么您需要手动查询格式化程序中的
IOException
”的含义。对于记录,
String.format(String,Object…)
实现为
returnnewformatter().format(format,args).toString()。因此,问题是为什么在使用
格式化程序时,OP需要“手动查询格式化程序”,就像
String.format
一样。
Files.write(path, () -> extendedModels.stream().distinct()
    .<CharSequence>map(x->String.format("import {%1$s} from './%1$s';\n", x)).iterator());
Formatter f=new Formatter(tsWriter);
extendedModels.stream().distinct().forEachOrdered(
    x -> f.format("import {%1$s} from './%1$s';\n", x));
f.flush();
if(f.ioException()!=null) throw f.ioException();