Java 8:用换行符和缩进格式化lambda [英] Java 8: Formatting lambda with newlines and indentation

查看:3654
本文介绍了Java 8:用换行符和缩进格式化lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



多行语句:

  String [] ppl = new String [] {Karen(F),Kevin(M),Lee(M),Joan(F) (M),Rick(M)}; 
列表< String> strings = Arrays.stream(ppl)
.filter(
(x) - >
{
return x.contains((M));
}
).collect(Collectors.toList());
strings.stream()。forEach(System.out :: println);

单行语句:

 列表与LT;字符串> string = Arrays.stream(ppl)
.map((x) - > x.toUpperCase())
.filter((x) - > x.contains((M)) )
.collect(Collectors.toList());




目前,Eclipse是自动格式化为以下内容:



多行语句:

  String [] ppl = new String [] {Karen(F),Kevin(M),Lee(M),Joan(F),Des(M),Rick(M)}; 
列表< String> strings = Arrays.stream(ppl).filter((x) - >
{
return x.contains((M));
})collect(Collectors.toList ());
strings.stream()。forEach(System.out :: println);

单行语句:

 

),Rick(M)};
列表< String> strings = Arrays.stream(ppl).map((x) - > x.toUpperCase())
.filter((x) - > x.contains((M)))。 Collectors.toList());
strings.stream()。forEach(System.out :: println);

我觉得这很麻烦,因为收集调用直接位于 return 之下,并且中间没有空格。我喜欢它,如果我可以启动一个新的行缩进的lambda,所以 .filter(调用将正好在 .collect之上(调用,但是可以使用标准Java-8 Eclipse Formatter定制的唯一的事情是在lambda体的开始处的括号,但是对于()括号,也不是缩进。



在单行调用的情况下,它只是使用基本的换行符,使其成为一个链接的混乱,我不认为我需要解释为什么这是很难解密之后。



有什么办法以某种方式自定义格式更多,实现第一在Eclipse中的格式化类型(或可选地,在另一个IDE,如IntelliJ IDEA。)






编辑:最接近我可以得到是IntelliJ IDEA 13社区版(阅读:免费版:P),这是以下(由连续缩进定义,在这种情况下是8):

 公共static void main(String [] args)
{
int [] x = new int [] {1,2,3,4,5,6,7};
int sum = Arrays.stream(x)
.map((n) - > n * 5)
.filter((n) - > {
System。 out.println(Filtering:+ n);
return n%3!= 0;
})
.reduce(0,Integer :: sum);

列表<整数> list = Arrays.stream(x)
.filter((n) - > n%2 == 0)
.map((n) - > n * 4)
。 boxed()
.collect(Collectors.toList());
list.forEach(System.out :: println);
System.out.println(sum);

它还允许对齐链接的方法调用,如下所示:

  int sum = Arrays.stream(x)
.map((n) - > n * 5)
.filter (n) - > {
System.out.println(Filtering:+ n);
return n%3!= 0;
})
.reduce 0,Integer :: sum);


列表<整数> list = Arrays.stream(x)
.filter((n) - > n%2 == 0)
.map((n) - > n * 4)
。 boxed()
.collect(Collectors.toList());
list.forEach(System.out :: println);
System.out.println(sum);
}

我个人发现,虽然更有意义,第二个版本推动它太多了,所以我更喜欢第一个。



负责首次设置的设置如下:

 <?xml version =1.0encoding =UTF-8?> 
< code_scheme name =Zhuinden>
< option name =JD_ALIGN_PARAM_COMMENTSvalue =false/>
< option name =JD_ALIGN_EXCEPTION_COMMENTSvalue =false/>
< option name =JD_ADD_BLANK_AFTER_PARM_COMMENTSvalue =true/>
< option name =JD_ADD_BLANK_AFTER_RETURNvalue =true/>
< option name =JD_P_AT_EMPTY_LINESvalue =false/>
< option name =JD_PARAM_DESCRIPTION_ON_NEW_LINEvalue =true/>
< option name =WRAP_COMMENTSvalue =true/>
< codeStyleSettings language =JAVA>
< option name =KEEP_FIRST_COLUMN_COMMENTvalue =false/>
< option name =BRACE_STYLEvalue =2/>
< option name =CLASS_BRACE_STYLEvalue =2/>
< option name =METHOD_BRACE_STYLEvalue =2/>
< option name =ELSE_ON_NEW_LINEvalue =true/>
< option name =WHILE_ON_NEW_LINEvalue =true/>
< option name =CATCH_ON_NEW_LINEvalue =true/>
< option name =FINALLY_ON_NEW_LINEvalue =true/>
< option name =ALIGN_MULTILINE_PARAMETERSvalue =false/>
< option name =SPACE_WITHIN_BRACESvalue =true/>
< option name =SPACE_BEFORE_IF_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_WHILE_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_FOR_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_TRY_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_CATCH_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_SWITCH_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_SYNCHRONIZED_PARENTHESESvalue =false/>
< option name =SPACE_BEFORE_ARRAY_INITIALIZER_LBRACEvalue =true/>
< option name =METHOD_PARAMETERS_WRAPvalue =1/>
< option name =EXTENDS_LIST_WRAPvalue =1/>
< option name =THROWS_LIST_WRAPvalue =1/>
< option name =EXTENDS_KEYWORD_WRAPvalue =1/>
< option name =THROWS_KEYWORD_WRAPvalue =1/>
< option name =METHOD_CALL_CHAIN_WRAPvalue =2/>
< option name =BINARY_OPERATION_WRAPvalue =1/>
< option name =BINARY_OPERATION_SIGN_ON_NEXT_LINEvalue =true/>
< option name =ASSIGNMENT_WRAPvalue =1/>
< option name =IF_BRACE_FORCEvalue =3/>
< option name =DOWHILE_BRACE_FORCEvalue =3/>
< option name =WHILE_BRACE_FORCEvalue =3/>
< option name =FOR_BRACE_FORCEvalue =3/>
< option name =PARAMETER_ANNOTATION_WRAPvalue =1/>
< option name =VARIABLE_ANNOTATION_WRAPvalue =1/>
< option name =ENUM_CONSTANTS_WRAPvalue =2/>
< / codeStyleSettings>
< / code_scheme>

我试图确保一切都是合理的,但我可能会弄乱一些东西,所以可能需要



如果您像匈牙利语一样使用匈牙利布局,那么这个键盘映射可能对您而言是不利的,因此您不会最终不能使用AltGR + F,AltGR + G,AltGR + B,AltGR + N和AltGR + M(对应于Ctrl + Alt)。

 <?xml version =1.0encoding =UTF-8?> 
< keymap version =1name =默认副本parent =$ default>
< action id =ExtractMethod>
< keyboard-shortcut first-keystroke =shift control M/>
< / action>
< action id =GotoImplementation>
< mouse-shortcut keystroke =control alt button1/>
< / action>
< action id =GotoLine>
< keyboard-shortcut first-keystroke =shift control G/>
< / action>
< action id =Inline>
< keyboard-shortcut first-keystroke =shift control O/>
< / action>
< action id =IntroduceField>
< keyboard-shortcut first-keystroke =shift control D/>
< / action>
< action id =Mvc.RunTarget>
< keyboard-shortcut first-keystroke =shift control P/>
< / action>
< action id =StructuralSearchPlugin.StructuralReplaceAction/>
< action id =Synchronize>
< keyboard-shortcut first-keystroke =shift control Y/>
< / action>
< / keymap>

虽然IntelliJ似乎没有提供一种方法来将lambda的大括号放在一个新的线,否则它是一个相当合理的格式化方式,所以我将其标记为接受。

解决方案

开箱即用IntelliJ



如果我这样写:

  // Mulit-Line语句
String [] ppl = new String [] {Karen(F),Kevin(M),Lee(M),Joan(F) ,Des(M),Rick(M)};
列表< String> strings = Arrays.stream(ppl)
.filter(
(x) - >
{
return x.contains((M));
}
).collect(Collectors.toList());
strings.stream()。forEach(System.out :: println);

然后应用自动格式化程序(无更改):

  // Mulit-Line语句
String [] ppl = new String [] {Karen(F),Kevin(M),Lee (M),Joan(F),Des(M),Rick(M)};
列表< String> strings = Arrays.stream(ppl)
.filter(
(x) - >
{
return x.contains((M));
}
).collect(Collectors.toList());
strings.stream()。forEach(System.out :: println);

您的单行语句也是如此。根据我的经验,IntelliJ在应用自动格式化方面更加灵活。 IntelliJ不太可能删除或添加行返回,如果你把它放在那里,那么它假设你想把它放在那里。 IntelliJ将乐意为您调整标签空间。






IntelliJ也可以配置为为您做一些。在设置 - >代码样式 - >java下,在包装和大括号选项卡中,您可以将链接方法调用设置为永久保留。



自动格式化之前

  // Mulit-Line语句
列表< String> strings = Arrays.stream(ppl).filter((x) - > {return x.contains((M));})。collect(Collectors.toList());

//单行语句
列表< String> strings()()()x(x) - x(x) - > x.contains((M)))collect(Collectors.toList ));

自动格式化后

  // Mulit-Line语句
列表< String> string = Arrays.stream(ppl)
.filter((x) - > {
return x.contains((M));
})
.collect (Collectors.toList());

//单行语句
列表< String> string = Arrays.stream(ppl)
.map((x) - > x.toUpperCase())
.filter((x) - > x.contains((M)) )
.collect(Collectors.toList());


What I would like to achieve with lambda indentation is the following:

Multi-line statement:

String[] ppl = new String[] { "Karen (F)", "Kevin (M)", "Lee (M)", "Joan (F)", "Des (M)", "Rick (M)" };
List<String> strings = Arrays.stream(ppl)
                         .filter(
                             (x) -> 
                             {
                                 return x.contains("(M)");
                             }
                         ).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

Single-line statement:

List<String> strings = Arrays.stream(ppl)
                         .map((x) -> x.toUpperCase())
                         .filter((x) -> x.contains("(M)"))
                         .collect(Collectors.toList());



Currently, Eclipse is auto-formatting to the following:

Multi-line statement:

String[] ppl = new String[] { "Karen (F)", "Kevin (M)", "Lee (M)", "Joan (F)", "Des (M)", "Rick (M)" };
List<String> strings = Arrays.stream(ppl).filter((x) ->
{
    return x.contains("(M)");
}).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

Single-line statement:

String[] ppl = new String[] { "Karen (F)", "Kevin (M)", "Lee (M)", "Joan (F)", "Des(M)", "Rick (M)" };
List<String> strings = Arrays.stream(ppl).map((x) -> x.toUpperCase())
        .filter((x) -> x.contains("(M)")).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

And I find this really messy, because of how the collect call is directly underneath the return and there's no space inbetween at all. I would prefer it if I could start the lambda in a new line indented, and so that the .filter( call would be right above the .collect( call. However, the only thing that can be customized with standard Java-8 Eclipse Formatter is the brace at the start of the lambda body, but nothing for the () brackets beforehand, nor the indentation.

And in the case of single-line calls, it just uses the basic line-wrap and makes it be a chained mess. I don't think I need to explain why this is hard to decrypt afterwards.

Is there any way to somehow customize the formatting more and achieve the first formatting type in Eclipse? (Or, optionally, in another IDE like IntelliJ IDEA.)



EDIT: The closest I could get was with IntelliJ IDEA 13 Community Edition (read: free edition :P) which was the following (defined by continuous indentation which in this case is 8):

public static void main(String[] args)
{
    int[] x = new int[] {1, 2, 3, 4, 5, 6, 7};
    int sum = Arrays.stream(x)
            .map((n) -> n * 5)
            .filter((n) -> {
                System.out.println("Filtering: " + n);
                return n % 3 != 0;
            })
            .reduce(0, Integer::sum);

    List<Integer> list = Arrays.stream(x)
            .filter((n) -> n % 2 == 0)
            .map((n) -> n * 4)
            .boxed()
            .collect(Collectors.toList());
    list.forEach(System.out::println);
    System.out.println(sum);    

It also allows to "align" the chained method invocation like this:

    int sum = Arrays.stream(x)
                    .map((n) -> n * 5)
                    .filter((n) -> {
                        System.out.println("Filtering: " + n);
                        return n % 3 != 0;
                    })
                    .reduce(0, Integer::sum);


    List<Integer> list = Arrays.stream(x)
                               .filter((n) -> n % 2 == 0)
                               .map((n) -> n * 4)
                               .boxed()
                               .collect(Collectors.toList());
    list.forEach(System.out::println);
    System.out.println(sum);
}

I personally find that while it makes more sense, the second version pushes it far too away, so I prefer the first one.

The setup responsible for the first setup is the following:

<?xml version="1.0" encoding="UTF-8"?>
<code_scheme name="Zhuinden">
  <option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
  <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
  <option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
  <option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
  <option name="JD_P_AT_EMPTY_LINES" value="false" />
  <option name="JD_PARAM_DESCRIPTION_ON_NEW_LINE" value="true" />
  <option name="WRAP_COMMENTS" value="true" />
  <codeStyleSettings language="JAVA">
    <option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
    <option name="BRACE_STYLE" value="2" />
    <option name="CLASS_BRACE_STYLE" value="2" />
    <option name="METHOD_BRACE_STYLE" value="2" />
    <option name="ELSE_ON_NEW_LINE" value="true" />
    <option name="WHILE_ON_NEW_LINE" value="true" />
    <option name="CATCH_ON_NEW_LINE" value="true" />
    <option name="FINALLY_ON_NEW_LINE" value="true" />
    <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
    <option name="SPACE_WITHIN_BRACES" value="true" />
    <option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_TRY_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" />
    <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
    <option name="METHOD_PARAMETERS_WRAP" value="1" />
    <option name="EXTENDS_LIST_WRAP" value="1" />
    <option name="THROWS_LIST_WRAP" value="1" />
    <option name="EXTENDS_KEYWORD_WRAP" value="1" />
    <option name="THROWS_KEYWORD_WRAP" value="1" />
    <option name="METHOD_CALL_CHAIN_WRAP" value="2" />
    <option name="BINARY_OPERATION_WRAP" value="1" />
    <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
    <option name="ASSIGNMENT_WRAP" value="1" />
    <option name="IF_BRACE_FORCE" value="3" />
    <option name="DOWHILE_BRACE_FORCE" value="3" />
    <option name="WHILE_BRACE_FORCE" value="3" />
    <option name="FOR_BRACE_FORCE" value="3" />
    <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
    <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
    <option name="ENUM_CONSTANTS_WRAP" value="2" />
  </codeStyleSettings>
</code_scheme>

I tried to make sure everything is reasonable, but I might have messed something up, so it might need minor adjustments.

If you're Hungarian like me and you're using a Hungarian layout, then this keymap might be of use to you, so that you don't end up not being able to use AltGR+F, AltGR+G, AltGR+B, AltGR+N and AltGR+M (which correspond to Ctrl+Alt).

<?xml version="1.0" encoding="UTF-8"?>
<keymap version="1" name="Default copy" parent="$default">
  <action id="ExtractMethod">
    <keyboard-shortcut first-keystroke="shift control M" />
  </action>
  <action id="GotoImplementation">
    <mouse-shortcut keystroke="control alt button1" />
  </action>
  <action id="GotoLine">
    <keyboard-shortcut first-keystroke="shift control G" />
  </action>
  <action id="Inline">
    <keyboard-shortcut first-keystroke="shift control O" />
  </action>
  <action id="IntroduceField">
    <keyboard-shortcut first-keystroke="shift control D" />
  </action>
  <action id="Mvc.RunTarget">
    <keyboard-shortcut first-keystroke="shift control P" />
  </action>
  <action id="StructuralSearchPlugin.StructuralReplaceAction" />
  <action id="Synchronize">
    <keyboard-shortcut first-keystroke="shift control Y" />
  </action>
</keymap>

While IntelliJ doesn't seem to provide a way to put the opening brace of the lambda in a new line, otherwise it's a fairly reasonable way of formatting, so I'll mark this as accepted.

解决方案

Out of the box IntelliJ 13 will probably work for you.

If I write it this way:

// Mulit-Line Statement
String[] ppl = new String[] { "Karen (F)", "Kevin (M)", "Lee (M)", "Joan (F)", "Des (M)", "Rick (M)" };
List<String> strings = Arrays.stream(ppl)
        .filter(
                (x) ->
                {
                    return x.contains("(M)");
                }
        ).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

And then apply the auto formatter (no changes):

// Mulit-Line Statement
String[] ppl = new String[]{"Karen (F)", "Kevin (M)", "Lee (M)", "Joan (F)", "Des (M)", "Rick (M)"};
List<String> strings = Arrays.stream(ppl)
        .filter(
                (x) ->
                {
                    return x.contains("(M)");
                }
        ).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

The same is true for your single line statement. It has been my experience that IntelliJ is more flexible in how its auto formatting is applied. IntelliJ is less likely to remove or add line returns, if you put it there then it assumes you meant to put it there. IntelliJ will happily adjust your tab-space for you.


IntelliJ can also be configured to do some of this for you. Under "settings" -> "code style" -> "java", in the "Wrapping and Braces" tab you can set "chain method calls" to "wrap always".

Before Auto-Formatting

// Mulit-Line Statement
List<String> strings = Arrays.stream(ppl).filter((x) -> { return x.contains("(M)"); }).collect(Collectors.toList());

// Single-Line Statement
List<String> strings = Arrays.stream(ppl).map((x) -> x.toUpperCase()).filter((x) -> x.contains("(M)")).collect(Collectors.toList());

After Auto-Formatting

// Mulit-Line Statement
List<String> strings = Arrays.stream(ppl)
        .filter((x) -> {
            return x.contains("(M)");
        })
        .collect(Collectors.toList());

// Single-Line Statement
List<String> strings = Arrays.stream(ppl)
        .map((x) -> x.toUpperCase())
        .filter((x) -> x.contains("(M)"))
        .collect(Collectors.toList());

这篇关于Java 8:用换行符和缩进格式化lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆