Java 8: форматирование лямбда с новыми строками и отступами
что я хотел бы достичь с помощью лямбда-отступа, так это следующее:
многострочный оператор:
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? (Или, необязательно, в другой IDE, такой как IntelliJ IDEA.)
EDIT: самое близкое, что я мог получить, было с IntelliJ IDEA 13 Community Edition (read: free 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+Ф, клавиши AltGr+г, клавиши AltGr+Б, клавиши AltGr+N и клавиши AltGr+м (что соответствует сочетание клавиш Ctrl+АЛТ).
<?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, похоже, не предоставляет способ поместить открывающую скобку лямбды в новую строку, в противном случае это довольно разумный способ форматирования, поэтому я отмечу это как принятое.
6 ответов:
из коробки 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 также может быть настроен, чтобы сделать это для вас. В разделе "Настройки" - > "стиль кода" - > " java "на вкладке" обертывание и фигурные скобки "вы можете установить" вызовы метода цепочки "на"обертывание всегда".
Перед Авто-Форматирование
// 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());
в Eclipse, для однострочных операторов:
в вашем проекте или глобальных настроек, перейдите к
Java -> Code Style -> Formatter -> Edit -> Line Wrapping -> Function Calls -> Qualified Invocations
, setWrap all elements, except first if not necessary
и галочкуForce split, even if line shorter than maximum line width
.
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
Я форматирую однострочный оператор, добавляя пустой комментарий "/ / " после функций.
List<Integer> list = Arrays.stream(x) // .filter((n) -> n % 2 == 0) // .map((n) -> n * 4) // .boxed() // .collect(Collectors.toList());
не идеально, но вы можете отключить форматер только для тех участков, которые немного плотные. Например
//@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 > стиль кода > форматер". Нажмите кнопку " Изменить..."кнопка, перейдите на вкладку" Off / On Tags " и включите теги.
этот вопрос теперь старый и, к сожалению, конфигурация по умолчанию Eclipse formatter по-прежнему не удобна для написания функционального кода читаемым способом.
я пробовал все вещи, упомянутые во всех других ответах, и никто не подходит для большинства случаев использования.
Это может быть хорошо для некоторых, но неприятно для других.я нашел способ, который подходит для меня большую часть времени.
Я разделяю его, думая, что это может помочь другие.обратите внимание, что мой путь имеет компромисс : принятие того, что каждый квалифицированный вызов всегда находится на отдельной строке.
Возможно, это недостающая опция в конфигурации форматирования : указание порога с точки зрения вызовов для обертывания строки вместо использования1
вызова по умолчанию.вот мои 2 комбинированных инструмента, чтобы справиться с этим довольно правильно:
настройка модуля форматирования Eclipse конфигурация для большинства случаев
создание шаблона кода с помощью
//@formatter:off ... //@formatter:on
для случаев углу.
настройка конфигурации Eclipse formatter
Значение для изменения окружены красным цветом в захвате.Шаг 1) Создайте свой собственный форматер кода Java
Preferences
меню и в дереве, перейдите кJava -> Code Style -> Formatter
.
Нажмите на кнопку "Создать", чтобы создать новыйProfile
(инициализируйте его с помощью "соглашений Java").два следующих шага должны быть выполнены в вашем пользовательском профиле форматирования.
Шаг 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". Готово!