Lo que me gustaría lograr con la sangría lambda es lo siguiente:
Declaración de varias líneas:
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);
Declaración de una sola línea:
List<String> strings = Arrays.stream(ppl)
.map((x) -> x.toUpperCase())
.filter((x) -> x.contains("(M)"))
.collect(Collectors.toList());
Actualmente, Eclipse se está formateando automáticamente a lo siguiente:
Declaración de varias líneas:
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);
Declaración de una sola línea:
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);
Y encuentro esto realmente complicado, debido a que la collect
llamada está directamente debajo del return
y no hay espacio entre ellos. Preferiría que pudiera iniciar el lambda en una nueva línea con sangría, y que la .filter(
llamada estuviera justo encima de la .collect(
llamada. Sin embargo, lo único que se puede personalizar con Java-8 Eclipse Formatter estándar es la llave al comienzo del cuerpo lambda, pero nada para los ()
corchetes de antemano, ni la sangría.
Y en el caso de las llamadas de una sola línea, solo usa el ajuste de línea básico y hace que sea un desastre encadenado. No creo que deba explicar por qué esto es difícil de descifrar después.
¿Hay alguna forma de personalizar más el formato de alguna manera y lograr el primer tipo de formato en Eclipse? (O, opcionalmente, en otro IDE como IntelliJ IDEA).
EDITAR: Lo más cercano que pude estar fue con IntelliJ IDEA 13 Community Edition (lea: edición gratuita: P) que era lo siguiente (definido por una sangría continua que en este caso es 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);
También permite "alinear" la invocación del método encadenado de esta manera:
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);
}
Personalmente, encuentro que si bien tiene más sentido, la segunda versión lo aleja demasiado, así que prefiero la primera.
La configuración responsable de la primera configuración es la siguiente:
<?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>
Traté de asegurarme de que todo fuera razonable, pero es posible que haya estropeado algo, por lo que es posible que necesite ajustes menores.
Si eres húngaro como yo y estás usando un diseño húngaro, entonces este mapa de teclas podría ser útil para ti, para que no termines sin poder usar AltGR + F, AltGR + G, AltGR + B , AltGR + N y AltGR + M (que corresponden a 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>
Si bien IntelliJ no parece proporcionar una forma de poner la llave de apertura de la lambda en una nueva línea, de lo contrario es una forma bastante razonable de formatear, así que marcaré esto como aceptado.
.filter(x -> x.contains("(M)"))
? Mucho más simple ... Si realmente está hablando de lugares donde necesita múltiples declaraciones, sería mejor dar un ejemplo que lo necesite.Ctrl+Alt+F
si está formateando automáticamente el código de otra persona.x
sin abrir la llave y cerrarla, por eso usé una declaración en lugar de la versión simple al principio.Respuestas:
IntelliJ 13 listo para usar probablemente funcionará para usted.
Si lo escribo de esta manera:
// 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);
Y luego aplique el formateador automático (sin cambios):
// 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);
Lo mismo es cierto para su declaración de una sola línea. Según mi experiencia, IntelliJ es más flexible en cómo se aplica su formateo automático. Es menos probable que IntelliJ elimine o agregue devoluciones de línea, si lo coloca allí, entonces asume que tenía la intención de colocarlo allí. IntelliJ ajustará felizmente su espacio de pestañas por usted.
IntelliJ también se puede configurar para hacer algo de esto por usted. En "configuración" -> "estilo de código" -> "java", en la pestaña "Envoltura y llaves" puede establecer "llamadas de método de cadena" a "envolver siempre".
Antes de formatear automáticamente
// 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());
Después del formateo automático
// 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());
fuente
En Eclipse, para las declaraciones de una sola línea:
En su proyecto o preferencias globales, vaya a
Java -> Code Style -> Formatter -> Edit -> Line Wrapping -> Function Calls -> Qualified Invocations
, configureWrap all elements, except first if not necessary
y marqueForce split, even if line shorter than maximum line width
.fuente
.filter(c -> c.getValue().equals(newValue))
, también se ajustarán justo antes de .equals. Sería bueno si tal configuración solo se aplicara al método relacionado con lambda; Sin embargo, veo que esto podría ser difícil de implementar ...Eclipse (Mars) tiene una opción para el formateador de expresiones lambda.
Ir
Window > Preferences > Java > Code Style > Formatter
Haga clic en el
Edit
botón, vaya a laBraces
etiqueta y establecer elLambda Body
aNext Line Indented
Otra opción es actualizar estas propiedades en la configuración de su proyecto. (
yourWorkspace > yourProject > .settings > org.eclipse.jdt.core.prefs
)fuente
Esta pregunta ahora es antigua y, desafortunadamente, la configuración predeterminada del formateador Eclipse sigue sin ser fácil de usar para escribir código funcional de una manera legible.
Probé todas las cosas mencionadas en todas las demás respuestas y nadie se adapta a la mayoría de los casos de uso.
Puede estar bien para algunos pero desagradable para otros.
Encontré una forma que se adapta a mí la mayor parte del tiempo.
Lo comparto pensando que podría ayudar a otros.
Tenga en cuenta que mi método tiene una compensación: aceptar que cada invocación calificada esté siempre en una línea distinta.
Quizás sea la opción que falta en la configuración del formateador: indicar el umbral en términos de invocaciones para envolver la línea en lugar de usar la
1
invocación por defecto.Aquí están mis 2 herramientas combinadas para manejarlo correctamente:
Personalización de la configuración del formateador Eclipse para la mayoría de los casos
Creación de una plantilla de código
//@formatter:off ... //@formatter:on
para casos de esquina.Personalización de la configuración del formateador de Eclipse
Los valores que se van a cambiar están rodeados de rojo en la captura.
Paso 1) Cree su propio formateador de estilo de código Java
Preferences
menú y en el árbol, vaya aJava -> Code Style -> Formatter
.Haga clic en "Nuevo" para crear uno nuevo
Profile
(inicialícelo con las "convenciones de Java").Los dos siguientes pasos deben realizarse en su perfil de formateador personalizado.
Paso 2) Cambie la configuración de sangría para líneas envueltas
La modificación permite utilizar espacios en blanco en lugar de tabulaciones.
Importará en el siguiente paso, ya que configuramos la política de ajuste de línea con la opción de sangría de columna.
Evitará de hecho crea espacios desagradables.
Paso 3) Cambie la sangría predeterminada para las líneas envueltas y la política de ajuste de línea para la invocación calificada
Aquí hay un formato de prueba con el código de la pregunta.
Antes de formatear:
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); }
Después de formatear:
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); }
Creación de plantillas de código
//@formatter:off ... //@formatter:on
para casos de esquina.Escribir manualmente o copiar y pegar
//@formatter:on
y//@formatter:off
está bien, ya que rara vez lo escribe.Pero si tiene que escribirlo varias veces a la semana o incluso peor durante el día, una forma más automática es bienvenida.
Paso 1) Vaya a la plantilla del Editor de Java
Preferences
menú y en el árbol, vaya aJava ->Editor -> Template
.Paso 2) Cree una plantilla para deshabilitar el formato del código seleccionado
Ahora puedes probarlo.
Seleccione las líneas que desea deshabilitar el formato.
Ahora ingrese
ctrl+space
dos veces (la primera es "propuestas de Java" y la segunda es "propuestas de plantilla").Deberías obtener algo como:
Seleccione la
fmt
plantilla como en la captura de pantalla y haga clic en "Entrar". ¡Hecho!fuente
Doy formato a la declaración de una sola línea agregando un comentario vacío "//" después de las funciones.
List<Integer> list = Arrays.stream(x) // .filter((n) -> n % 2 == 0) // .map((n) -> n * 4) // .boxed() // .collect(Collectors.toList());
fuente
No es ideal, pero puede desactivar el formateador solo para aquellas secciones que son un poco densas. Por ejemplo
//@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
Vaya a "Ventana> Preferencias> Java> Estilo de código> Formateador". Haga clic en el botón "Editar ...", vaya a la pestaña "Desactivar / Activar etiquetas" y habilite las etiquetas.
fuente
La opción que funcionó para mí fue marcar la
Never join already wrapped lines
opción en la sección Ajuste de línea del Formateador en Preferencias.fuente
Si aún no tiene un formateador de Eclipse personalizado:
Preferencias de Eclipse Java> Estilo de código> Formateador Nuevo Ingrese un nombre Haga clic en Aceptar Saltos de línea de control
Editar el perfil Pestaña de ajuste de línea Marque "Nunca unir líneas ya ajustadas"
Terminará así
String phrase = employeeList .stream() .filter(p -> p.getAge() >= 33) .map(p -> p.getFirstName()) .collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));
Necesito escribir cada. empezar en la siguiente línea
créditos - https://www.selikoff.net/2017/07/02/eclipse-and-line-wrapping/
fuente
La última versión de Eclipse tiene un formateador integrado de formato java 8, goto
Preferences -> Java -> Code Style -> Formatter -> Active profile and Select Eclipse 2.1[built-in] profile
fuente