To, co chciałbym osiągnąć za pomocą wcięcia lambda, jest następujące:
Instrukcja wielowierszowa:
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);
Instrukcja jednowierszowa:
List<String> strings = Arrays.stream(ppl)
.map((x) -> x.toUpperCase())
.filter((x) -> x.contains("(M)"))
.collect(Collectors.toList());
Obecnie Eclipse automatycznie formatuje w następujący sposób:
Instrukcja wielowierszowa:
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);
Instrukcja jednowierszowa:
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);
Uważam, że jest to naprawdę nieporządne, ponieważ collect
połączenie jest bezpośrednio pod spodem return
i nie ma między nimi żadnej przestrzeni. Wolałbym, gdybym mógł rozpocząć lambdę w nowym wierszu z wcięciem, tak aby .filter(
wywołanie znajdowało się tuż nad .collect(
wywołaniem. Jednak jedyną rzeczą, którą można dostosować za pomocą standardowego komponentu Java-8 Eclipse Formatter, jest nawias klamrowy na początku ciała lambda, ale nie ma ()
wcześniejszego nawiasu ani wcięcia.
A w przypadku połączeń jednowierszowych po prostu używa podstawowego zawijania linii i sprawia, że jest to łańcuchowy bałagan. Chyba nie muszę wyjaśniać, dlaczego później trudno to odszyfrować.
Czy jest jakiś sposób, aby w jakiś sposób bardziej dostosować formatowanie i osiągnąć pierwszy typ formatowania w Eclipse? (Lub opcjonalnie w innym IDE, takim jak IntelliJ IDEA).
EDYCJA: Najbliższe, jakie mogłem uzyskać, było z IntelliJ IDEA 13 Community Edition (czytaj: wydanie bezpłatne: P), które było następujące (zdefiniowane przez ciągłe wcięcie, które w tym przypadku wynosi 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);
Pozwala także na „wyrównanie” połączonego wywołania metody w następujący sposób:
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);
}
Osobiście uważam, że chociaż ma to większy sens, druga wersja odsuwa ją zdecydowanie za daleko, więc wolę pierwszą.
Konfiguracja odpowiedzialna za pierwszą konfigurację jest następująca:
<?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>
Próbowałem się upewnić, że wszystko jest rozsądne, ale mogłem coś zepsuć, więc może wymagać drobnych poprawek.
Jeśli jesteś Węgrem, tak jak ja i używasz układu węgierskiego, ta mapa klawiszy może ci się przydać, więc nie będziesz w stanie użyć AltGR + F, AltGR + G, AltGR + B , AltGR + N i AltGR + M (co odpowiada 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>
Chociaż IntelliJ nie wydaje się zapewniać sposobu na umieszczenie nawiasu otwierającego lambda w nowej linii, w przeciwnym razie jest to dość rozsądny sposób formatowania, więc oznaczę to jako zaakceptowane.
.filter(x -> x.contains("(M)"))
? Dużo prostsze ... Jeśli faktycznie mówisz o miejscach, w których potrzebujesz wielu stwierdzeń, lepiej byłoby podać przykład, który tego potrzebował.Ctrl+Alt+F
jeśli automatycznie formatujesz czyjś kod.x
bez otwierania nawiasu klamrowego i zamykania go, dlatego na początku użyłem oświadczenia zamiast prostej wersji.Odpowiedzi:
Po wyjęciu z pudełka IntelliJ 13 prawdopodobnie będzie dla Ciebie działać.
Jeśli napiszę to w ten sposób:
// 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);
A następnie zastosuj automatyczny formatter (bez zmian):
// 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);
To samo dotyczy instrukcji jednowierszowych. Z mojego doświadczenia wynika, że IntelliJ jest bardziej elastyczny w stosowaniu automatycznego formatowania. IntelliJ rzadziej usunie lub doda zwroty linii, jeśli umieścisz go tam, to zakłada, że zamierzałeś go tam umieścić. IntelliJ z przyjemnością dostosuje dla Ciebie miejsce na karcie.
IntelliJ można również skonfigurować tak, aby zrobił to za Ciebie. W sekcji „ustawienia” -> „styl kodu” -> „java”, w zakładce „Zawijanie i nawiasy klamrowe” można ustawić „łańcuchowe wywołania metod” na „zawijaj zawsze”.
Przed automatycznym formatowaniem
// 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());
Po automatycznym formatowaniu
// 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());
źródło
W Eclipse dla instrukcji jednowierszowych:
W swoim projekcie lub preferencjach globalnych przejdź do
Java -> Code Style -> Formatter -> Edit -> Line Wrapping -> Function Calls -> Qualified Invocations
, ustawWrap all elements, except first if not necessary
i zaznaczForce split, even if line shorter than maximum line width
.źródło
.filter(c -> c.getValue().equals(newValue))
Będą również zawijane tuż przed .equals. Byłoby fajnie, gdyby takie ustawienie dotyczyło tylko metody związanej z lambdą; Widzę, że może to być trudne do zrealizowania ...Eclipse (Mars) ma opcję programu formatującego wyrażenia lambda.
Iść do
Window > Preferences > Java > Code Style > Formatter
Kliknij
Edit
przycisk, przejdź doBraces
znacznika i ustawLambda Body
naNext Line Indented
Inną opcją jest zaktualizowanie tych właściwości w ustawieniach projektu. (
yourWorkspace > yourProject > .settings > org.eclipse.jdt.core.prefs
)źródło
To pytanie jest teraz stare i niestety domyślna konfiguracja programu formatującego Eclipse nadal nie jest przyjazna dla użytkownika do pisania kodu funkcjonalnego w czytelny sposób.
Wypróbowałem wszystkie rzeczy wymienione we wszystkich innych odpowiedziach i nikt nie pasuje do większości przypadków użycia.
Dla niektórych może to być dobre, ale dla innych nieprzyjemne.
Przez większość czasu znalazłem sposób, który mi odpowiada.
Dzielę się tym, myśląc, że może to pomóc innym.
Zauważ, że mój sposób wymaga kompromisu: zaakceptowanie, że każde kwalifikowane wywołanie zawsze znajduje się w odrębnej linii.
Być może jest to brakująca opcja w konfiguracji programu formatującego: wskazanie progu pod względem wywołań do zawijania wiersza zamiast używania
1
wywołania domyślnie.Oto moje 2 połączone narzędzia do obsługi raczej poprawnie:
Dostosowywanie konfiguracji programu formatującego Eclipse w większości przypadków
Tworzenie szablonu kodu
//@formatter:off ... //@formatter:on
dla przypadków narożnych.Dostosowywanie konfiguracji programu formatującego Eclipse
Wartości do zmiany są zaznaczone na czerwono w przechwyceniu.
Krok 1) Utwórz własny program do formatowania stylu kodu w języku Java
Preferences
menu iw drzewie przejdź doJava -> Code Style -> Formatter
.Kliknij „Nowy”, aby utworzyć nowy
Profile
(zainicjuj go z „Konwencjami Java”).Dwa następne kroki należy wykonać w swoim niestandardowym profilu formatyzatora.
Krok 2) Zmień konfigurację wcięć dla zawijanych wierszy
Modyfikacja pozwala na użycie białych znaków zamiast tabel.
Będzie to miało znaczenie w następnym kroku, ponieważ skonfigurujemy zasady zawijania wierszy z opcją wcięcia kolumny.
Uniknie, rzeczywiście, tworzy nieprzyjemne przestrzenie.
Krok 3) Zmień domyślne wcięcie dla zawijanych wierszy i zasady zawijania wierszy dla kwalifikowanego wywołania
Oto formatowanie testu z kodem pytania.
Przed formatowaniem:
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); }
Po sformatowaniu:
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); }
Tworzenie szablonów kodu
//@formatter:off ... //@formatter:on
dla przypadków narożnych.Pisanie ręczne lub kopiowaniem wklej
//@formatter:on
i//@formatter:off
jest w porządku jak piszesz to rzadko.Ale jeśli musisz pisać to kilka razy w tygodniu lub gorzej w ciągu dnia, mile widziany jest bardziej automatyczny sposób.
Krok 1) Przejdź do szablonu Java Editor
Preferences
menu iw drzewie przejdź doJava ->Editor -> Template
.Krok 2) Utwórz szablon, aby wyłączyć formatowanie dla wybranego kodu
Możesz to teraz przetestować.
Wybierz linie, dla których chcesz wyłączyć formatowanie.
Teraz wprowadź
ctrl+space
dwukrotnie (pierwsza to „Propozycje Java”, a druga to „Propozycje szablonów”).Powinieneś dostać coś takiego:
Wybierz
fmt
szablon jak na zrzucie ekranu i kliknij „Enter”. Gotowe!źródło
Formatuję instrukcję jednowierszową, dodając pusty komentarz „//” po funkcjach.
List<Integer> list = Arrays.stream(x) // .filter((n) -> n % 2 == 0) // .map((n) -> n * 4) // .boxed() // .collect(Collectors.toList());
źródło
Nie jest to idealne rozwiązanie, ale możesz wyłączyć formatyzator tylko dla tych sekcji, które są trochę gęste. Na przykład
//@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
Wybierz „Okno> Preferencje> Java> Styl kodu> Formatyzator”. Kliknij przycisk „Edytuj ...”, przejdź do zakładki „Wyłącz / Włącz tagi” i włącz tagi.
źródło
Opcją, która działała dla mnie, było zaznaczenie
Never join already wrapped lines
opcji w sekcji Zawijanie linii w programie Formatter w Preferencjach.źródło
Jeśli nie masz jeszcze niestandardowego programu formatującego Eclipse:
Preferencje Eclipse Java> Styl kodu> Formatter Nowy Wprowadź nazwę Kliknij OK Kontroluj podziały wierszy
Edytuj profil Zakładka Zawijanie linii Zaznacz „Nigdy nie dołączaj już zawiniętych linii”
To się tak skończy
String phrase = employeeList .stream() .filter(p -> p.getAge() >= 33) .map(p -> p.getFirstName()) .collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));
Trzeba wpisać co. zacznij w następnej linii
kredyty - https://www.selikoff.net/2017/07/02/eclipse-and-line-wrapping/
źródło
Najnowsza wersja Eclipse ma wbudowane formatowanie java 8, goto
Preferences -> Java -> Code Style -> Formatter -> Active profile and Select Eclipse 2.1[built-in] profile
źródło