자바 8 : 줄 바꿈 및 들여 쓰기로 람다 서식 지정


82

람다 들여 쓰기로 달성하고 싶은 것은 다음과 같습니다.

여러 줄 문 :

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);

한 줄 문 :

List<String> strings = 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)" };
List<String> strings = Arrays.stream(ppl).filter((x) ->
{
    return x.contains("(M)");
}).collect(Collectors.toList());
strings.stream().forEach(System.out::println);

한 줄 문 :

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);

collect전화가 바로 아래에 return있고 그 사이에 공간이 전혀 없기 때문에 이것은 정말 지저분 합니다. 들여 쓰기 된 새 줄에서 람다를 시작할 수 있고 .filter(호출이 호출 바로 위에 있도록하려면 선호합니다 .collect(. 그러나 표준 Java-8 Eclipse Formatter로 사용자 정의 할 수있는 유일한 것은 람다 본문의 시작 부분에있는 중괄호이지만 ()사전에 대괄호 나 들여 쓰기를 위한 것은 없습니다 .

그리고 단일 회선 호출의 경우 기본 줄 바꿈을 사용하여 체인이 엉망이됩니다. 나중에 이것이 왜 해독이 어려운지 설명 할 필요가 없다고 생각합니다.

어떻게 든 형식을 사용자 정의하고 Eclipse에서 첫 번째 형식화 유형을 달성하는 방법이 있습니까? (또는 선택적으로 IntelliJ IDEA와 같은 다른 IDE에서.)



편집 : 내가 얻을 수있는 가장 가까운 것은 IntelliJ IDEA 13 Community Edition (읽기 : 무료 버전 : P)으로 다음과 같았습니다 (이 경우 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);    

또한 다음과 같이 연결된 메서드 호출을 "정렬"할 수 있습니다.

    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);
}

나는 개인적으로 그것이 더 의미가 있지만 두 번째 버전이 너무 멀리 밀려서 첫 번째 버전을 선호한다는 것을 개인적으로 발견했습니다.

첫 번째 설정을 담당하는 설정은 다음과 같습니다.

<?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>

모든 것이 합리적인지 확인하려고 노력했지만 뭔가 엉망이되었을 수 있으므로 약간의 조정이 필요할 수 있습니다.

나처럼 헝가리어이고 헝가리어 레이아웃을 사용하는 경우이 키맵이 유용 할 수 있으므로 AltGR + F, AltGR + G, AltGR + B를 사용할 수 없게됩니다. , AltGR + N 및 AltGR + M (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>

IntelliJ는 람다의 여는 중괄호를 새 줄에 넣는 방법을 제공하지 않는 것 같지만 그렇지 않으면 상당히 합리적인 형식 지정 방법이므로 수락 된 것으로 표시합니다.


10
사용할 수 없습니까 .filter(x -> x.contains("(M)"))? 훨씬 더 간단합니다 ... 실제로 여러 문장이 필요한 곳에 대해 이야기 하고 있다면 , 필요한 예를 제공하는 것이 좋습니다.
Jon Skeet 2014

@JonSkeet 지금은 여러 줄에 대해 정말 좋은 사용 사례를 생각할 수 없었지만 대신 두 사례를 모두 추가했습니다.
EpicPandaForce

2
솔직히 누군가 아래에 게시하고 삭제 한 'Netbeans 8.0'버전은 진실에 가깝지만 Netbeans는 문의 여는 중괄호를 Allman 스타일로 적절하게 형식화하지 않는 것으로 악명이 높습니다.
EpicPandaForce

3
현재 솔루션은 "줄 바꿈 된 줄에 결합하지 않음"과 수동 서식 지정을 활성화하는 것 같지만 Ctrl+Alt+F다른 사람의 코드 서식을 자동으로 지정하는 경우 누르는 것과 비교하면 다소 지루해 보입니다 .
EpicPandaForce

그리고 어떤 이유로 Eclipse는 x중괄호를 열고 닫지 않고 유형을 파악하는 데 문제가 있었기 때문에 처음에는 단순한 버전이 아닌 명령문을 사용했습니다.
EpicPandaForce

답변:


29

즉시 사용 가능한 IntelliJ 13은 아마도 당신을 위해 일할 것입니다.

이렇게 작성하면 :

// 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);

그런 다음 자동 포맷터를 적용합니다 (변경 사항 없음).

// 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);

한 줄 문도 마찬가지입니다. IntelliJ가 자동 서식이 적용되는 방식이 더 유연하다는 것은 제 경험이었습니다. IntelliJ는 줄 반환을 제거하거나 추가 할 가능성이 적습니다. 거기에 넣으면 거기에 넣을 예정이라고 가정합니다. IntelliJ는 기꺼이 탭 공간을 조정할 것입니다.


IntelliJ는이 작업 중 일부를 수행하도록 구성 할 수도 있습니다. "settings"-> "code style"-> "java"아래의 "Wrapping and Braces"탭에서 "연쇄 메소드 호출"을 "항상 랩"으로 설정할 수 있습니다.

자동 서식 지정 전

// 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());

자동 서식 후

// 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());

문제는이 방식으로 자동으로 서식을 지정할 수 있다는 것입니다. 자동 서식 지정이 내가 좋아하는 코드 스타일로 서식을 지정하면 문제가 간단 해집니다. 그러면 다른 사람의 코드도 쉽게 읽을 수 있습니다.
EpicPandaForce

@Zhuinden 한 줄 문에 대해이 작업을 수행하는 방법에 대한 예제로 답변을 업데이트했습니다. 표시된 것처럼 여러 줄 문에 대해 어느 정도 작동합니다. IntelliJ의 자동 포맷터를 구성하는 데는 많은 옵션이 있습니다. 질문에있는대로 정확하게 나타나도록 수정할 수 있습니다.
Mike Rylander

위에서 붙여 넣은 XML에 따라 설정했습니다. Android가 아닌 경우 Eclipse 대신 IntelliJ를 사용할 것 같습니다. 감사.
EpicPandaForce

1
@EpicPandaForce Android에서도 사용하지 않는 이유는 무엇입니까?
herman 2014

@herman 기술적으로 저는 그 이후로 Android 용 Android Studio를 사용하기 시작했습니다. 몇 기가의 RAM을 추가로 설치해야했지만 회사에 약간의 RAM이 있었기 때문에 이제 8GB로 컴파일하는 동안 Gradle이 전체 컴퓨터를 정지시키지 않습니다. P
EpicPandaForce

59

Eclipse에서 단일 행 명령문의 경우 :

프로젝트 또는 전역 환경 설정에서 Java -> Code Style -> Formatter -> Edit -> Line Wrapping -> Function Calls -> Qualified Invocations, 설정 Wrap all elements, except first if not necessary및 선택으로 이동합니다 Force split, even if line shorter than maximum line width.


이봐, 내가 들여 쓰기를 강요받는 것을 제외하고는 괜찮아 보인다. 기본 들여 쓰기 나 열이나 1로도 그것도 말이되지 않는다. 내 들여 쓰기는 현재에 따라 다릅니다. 예 : 최종 List <DataRow> days = MappedSelect.query ( "gameDays", DataRow.class) .param ( "seasonId", 20142015) .select (context); 위의 경우 다음 두 줄이 이전 줄 점에서 정확히 들여 쓰기를 원합니다.
Saravana Kumar M

1
거의 완벽합니다! :-) 때로는 내 취향에 비해 너무 많이 래핑됩니다. 예를 들어 람다 내의 문 .filter(c -> c.getValue().equals(newValue))은 .equals 바로 전에 래핑됩니다. 그러한 설정이 람다 관련 방법에만 적용된다면 누구에게 좋을까요? 나는이 ...하지만 구현하기 어려울 수 있습니다 볼
도미닉

24

Eclipse (Mars)에는 람다 식 포맷터 옵션이 있습니다.

이동 Window > Preferences > Java > Code Style > Formatter

여기에 이미지 설명 입력

Edit버튼을 클릭하고 Braces태그 로 이동 Lambda Body하여Next Line Indented

여기에 이미지 설명 입력

또 다른 옵션은 이러한 속성을 프로젝트 설정으로 업데이트하는 것입니다. ( yourWorkspace > yourProject > .settings > org.eclipse.jdt.core.prefs)

org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=next_line_shifted

2
이것은 괄호로 묶인 람다에만 도움이되는 것 같습니다.
Nick

이러한 속성을 업데이트하는 것은 도움이되지 않습니다
Piotr Wittchen

19

이 질문은 이제 오래되었고 안타깝게도 Eclipse 포맷터의 기본 구성은 읽기 쉬운 방식으로 기능 코드를 작성하는 데 여전히 사용자 친화적이지 않습니다.

나는 다른 모든 답변에서 언급 된 모든 것을 시도했지만 대부분의 사용 사례에 적합한 사람은 없습니다.
어떤 사람들에게는 괜찮지 만 다른 사람들에게는 불쾌 할 수 있습니다.

대부분의 경우 나에게 적합한 방법을 찾았습니다.
나는 그것이 다른 사람들에게 도움이 될 수 있다고 생각함으로써 그것을 공유합니다.

내 방식에는 트레이드 오프가 있다는 점에 유의하십시오. 각 정규화 된 호출이 항상 별개의 줄에 있음을 수락합니다.
포맷터 구성에서 누락 된 옵션 일 수 있습니다. 사용하는 대신 줄을 래핑하는 호출 측면에서 임계 값을 나타냅니다.1 기본적으로 호출 .

다음은 올바르게 처리하는 두 가지 도구입니다.

  • 대부분의 경우 Eclipse 포맷터 구성 사용자 정의

  • //@formatter:off ... //@formatter:on코너 케이스용으로 코드 템플릿 만들기 .


Eclipse 포맷터 구성 사용자 정의
변경할 값은 캡처에서 빨간색으로 둘러싸여 있습니다.

1 단계) 고유 한 Java 코드 스타일 포맷터 만들기

Preferences메뉴와 트리에서로 이동합니다 Java -> Code Style -> Formatter.
"새로 만들기"를 클릭하여 새 파일을 만듭니다 Profile( "Java 규칙"로 초기화).

Eclipse 포맷터

다음 두 단계는 사용자 지정 포맷터 프로필에서 수행해야합니다.

2 단계) 줄 바꿈 된 줄 들여 쓰기 구성 변경

식별 구성

수정을 통해 표 대신 공백을 사용할 수 있습니다.
열 들여 쓰기 옵션으로 줄 바꿈 정책을 구성 할 때 다음 단계에서 중요합니다.
실제로 불쾌한 공간을 만드는 것을 피할 것입니다.

3 단계) 줄 바꿈 된 줄의 기본 들여 쓰기 및 한정된 호출을위한 줄 바꿈 정책 변경

줄 바꿈 된 선 크기


다음은 질문 코드가 포함 된 테스트 형식입니다.

포맷하기 전에 :

void multiLineStatements() {
    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);
}

void singleLineStatements() {
    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);
}

포맷 후 :

void multiLineStatements() {
    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);
}

void singleLineStatements() {
    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);
}

//@formatter:off ... //@formatter:on코너 케이스용으로 코드 템플릿 만들기 .

수동으로 작성하거나 복사 - 붙여 넣기 //@formatter:on//@formatter:off당신이 거의 그것을 쓸로 괜찮습니다.
그러나 일주일에 여러 번 또는 더 나쁘게 작성해야하는 경우보다 자동적 인 방법을 사용하는 것이 좋습니다.

1 단계) Java 편집기 템플릿으로 이동

Preferences메뉴와 트리에서로 이동합니다 Java ->Editor -> Template.
여기에 이미지 설명 입력

2 단계) 선택한 코드의 서식을 비활성화하는 템플릿 만들기

템플릿 포맷터 끄기 켜기

이제 테스트 할 수 있습니다.
서식을 비활성화 할 줄을 선택합니다.
이제 ctrl+space두 번 입력합니다 (첫 번째는 "Java 제안"이고 두 번째는 "템플릿 제안").
다음과 같은 것을 얻을 수 있습니다.

템플릿 제안

fmt스크린 샷에서와 같이 템플릿을 선택하고 "Enter"를 클릭합니다. 끝난!

템플릿 적용 후 결과


16

함수 뒤에 빈 주석 "//"을 추가하여 한 줄 문 형식을 지정합니다.

List<Integer> list = Arrays.stream(x) //
                           .filter((n) -> n % 2 == 0) //
                           .map((n) -> n * 4) //
                           .boxed() //
                           .collect(Collectors.toList());

3
쉽고 효과적입니다.
Steve

12
IDE 스타일 구성을 설정하지 않은 코드베이스의 소음이라고 생각합니다. 코드베이스를 처음 보는 사람들에게는 혼란 스러울 수 있습니다.
Marc Bouvier

9

이상적은 아니지만 약간 조밀 한 섹션에 대해서만 포맷터를 끌 수 있습니다. 예를 들면

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

"창> 환경 설정> Java> 코드 스타일> 포맷터"로 이동하십시오. "Edit ..."버튼을 클릭하고 "Off / On Tags"탭으로 이동하여 태그를 활성화합니다.


3
이것은 내 서식 올바른 얻을 수있는 ungeeky하지만 간단한 옵션 듯
SMC

2

나를 위해 일한 Never join already wrapped lines옵션은 환경 설정에서 포맷터의 줄 바꿈 섹션에있는 옵션을 선택하는 것이 었습니다 .


1

사용자 정의 Eclipse 포맷터가 아직없는 경우 :

Eclipse 환경 설정 Java> 코드 스타일> 포맷터 새로 만들기 이름 입력 확인 클릭 줄 바꿈 제어

프로파일 줄 바꿈 탭 편집 "이미 줄 바꿈하지 않음"을 선택합니다.

이렇게 끝날거야

    String phrase = employeeList
            .stream()
            .filter(p -> p.getAge() >= 33)
            .map(p -> p.getFirstName())
            .collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));

모든. 다음 줄에서 시작

크레딧-https: //www.selikoff.net/2017/07/02/eclipse-and-line-wrapping/


-1

최신 버전의 Eclipse에는 기본 제공 포맷터 Java 8 형식이 있습니다.

Preferences -> Java -> Code Style -> Formatter -> Active profile

and Select Eclipse 2.1[built-in] profile
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.