Java 8: Lambda'yı satırsonu ve girintiyle biçimlendirme


83

Lambda girintisi ile elde etmek istediğim şey şudur:

Çok satırlı açıklama:

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

Tek satırlık açıklama:

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



Şu anda Eclipse, aşağıdaki şekilde otomatik olarak biçimlendirmektedir:

Çok satırlı açıklama:

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

Tek satırlık açıklama:

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

Ve bunu gerçekten karmaşık buluyorum, çünkü collectaramanın doğrudan altında olması returnve aralarında hiç boşluk olmaması. Lambda'yı girintili yeni bir satırda başlatmayı tercih ederim ve böylece .filter(çağrı çağrının hemen üstünde olur .collect(. Bununla birlikte, standart Java-8 Eclipse Formatter ile özelleştirilebilen tek şey, lambda gövdesinin başlangıcındaki ayraçtır, ancak ()önceden parantezler veya girinti için hiçbir şey yoktur .

Ve tek hatlı aramalarda, sadece temel hat sarmayı kullanır ve bunu zincirleme bir karmaşa haline getirir. Bunun daha sonra şifresini çözmenin neden zor olduğunu açıklamama gerek olduğunu sanmıyorum.

Biçimlendirmeyi bir şekilde daha fazla özelleştirmenin ve Eclipse'de ilk biçimlendirme türünü elde etmenin bir yolu var mı? (Veya isteğe bağlı olarak IntelliJ IDEA gibi başka bir IDE'de.)



DÜZENLEME: En yakın bulabildiğim IntelliJ IDEA 13 Community Edition (okuma: ücretsiz sürüm: P) ile oldu (bu durumda 8 olan sürekli girinti ile tanımlanmıştır):

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

Ayrıca, zincirleme yöntem çağrısını şu şekilde "hizalamaya" izin verir:

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

Şahsen ben ikinci versiyonun daha mantıklı olmasına rağmen onu çok uzağa ittiğini görüyorum, bu yüzden ilkini tercih ediyorum.

İlk kurulumdan sorumlu kurulum şu şekildedir:

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

Her şeyin mantıklı olduğundan emin olmaya çalıştım, ancak bir şeyleri mahvetmiş olabilirim, bu yüzden küçük ayarlamalara ihtiyaç olabilir.

Benim gibi bir Macarsanız ve bir Macar düzeni kullanıyorsanız, bu tuş eşlemesi sizin için yararlı olabilir, böylece AltGR + F, AltGR + G, AltGR + B'yi kullanamazsınız. , AltGR + N ve AltGR + M (Ctrl + Alt'a karşılık gelir).

<?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, lambda'nın açılış parantezini yeni bir satıra koymanın bir yolunu sağlamıyor gibi görünse de, aksi takdirde oldukça makul bir biçimlendirme yolu, bu yüzden bunu kabul edildi olarak işaretleyeceğim.


10
Kullanamaz .filter(x -> x.contains("(M)"))mısın Çok daha basit ... Aslında birden fazla ifadeye ihtiyaç duyduğunuz yerlerden bahsediyorsanız, buna ihtiyaç duyan bir örnek vermek daha iyi olacaktır.
Jon Skeet

@JonSkeet Şu anda çoklu hat için gerçekten iyi bir kullanım durumu düşünemedim, ancak bunun yerine her iki durumu da ekledim.
EpicPandaForce

2
Dürüst olmak gerekirse, birisinin aşağıda gönderdiği ve sildiği 'Netbeans 8.0' sürümü gerçeğe çok yakındı, ancak Netbeans, ifadelerin açılış parantezlerini Allman stiline uygun şekilde biçimlendirmeye izin vermemesiyle ünlü.
EpicPandaForce

3
Sanırım şu anki çözüm "sarmalanmış satırları asla birleştirmeyin" ve elle biçimlendirmeyi mümkün kılıyor, ancak bu, Ctrl+Alt+Fbaşka birinin kodunu otomatik olarak biçimlendiriyorsanız , basmaya kıyasla biraz sıkıcı görünüyor .
EpicPandaForce

Ve bazı nedenlerden dolayı Eclipse, xküme ayracı açmadan ve kapatmadan türünü bulmakta sorunlar yaşıyordu , bu yüzden neden ilk başta basit sürüm yerine bir ifade kullandım.
EpicPandaForce

Yanıtlar:


30

Kutudan çıkar çıkmaz IntelliJ 13 muhtemelen sizin için çalışacaktır.

Bu şekilde yazarsam:

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

Ve sonra otomatik biçimlendiriciyi uygulayın (değişiklik yok):

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

Aynı şey tek satırlık ifadeniz için de geçerlidir. IntelliJ'in otomatik biçimlendirmenin nasıl uygulandığı konusunda daha esnek olduğunu deneyimledim. IntelliJ'in satır iadelerini kaldırma veya ekleme olasılığı daha düşüktür, eğer oraya koyarsanız, oraya koymak istediğinizi varsayar. IntelliJ, sekme alanınızı sizin için mutlu bir şekilde ayarlayacaktır.


IntelliJ, bunların bir kısmını sizin için yapacak şekilde de yapılandırılabilir. "Ayarlar" -> "kod stili" -> "java" altında, "Sarma ve Ayraçlar" sekmesinde "zincir yöntemi çağrılarını" "her zaman kaydır" olarak ayarlayabilirsiniz.

Otomatik Biçimlendirmeden Önce

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

Otomatik Biçimlendirmeden Sonra

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

Soru şu ki, bu şekilde otomatik olarak biçimlendirebilir mi? Otomatik biçimlendirme, kodu biçimlendirmeyi sevdiğim şekilde biçimlendirmede iyi bir iş çıkarırsa sorunu basitleştirir, bu şekilde herhangi bir kodun başkalarının kodunu okuması daha kolaydır.
EpicPandaForce

@Zhuinden Tek satırlık bir ifade için bunun nasıl yapılacağına dair bir örnekle cevabı güncelledim. Gösterildiği gibi, bir dereceye kadar çok satırlı ifade için de işe yarar. IntelliJ'in otomatik formatlayıcısını yapılandırmak için pek çok seçenek vardır, muhtemelen tam olarak sorduğunuz gibi görünmesi için onu iyileştirebilirsiniz.
Mike Rylander

İşleri yukarıda yapıştırdığım XML'e göre ayarlıyorum, sanırım Android olmayan herhangi bir şey için Eclipse yerine IntelliJ kullanacağım. Teşekkürler.
EpicPandaForce

1
@EpicPandaForce neden Android için de kullanmayasınız?
herman

@herman teknik olarak o zamandan beri Android için Android Studio kullanmaya başladım. Birkaç ekstra RAM yüklemem gerekiyordu, ancak firma şu anda 8 GB'lık bir yere sahipti, Gradle derleme sırasında tüm bilgisayarı
dondurmuyor

59

Eclipse'de tek satırlık ifadeler için:

Projenizde veya global tercihlerinizde gidin Java -> Code Style -> Formatter -> Edit -> Line Wrapping -> Function Calls -> Qualified Invocations, ayarlayın Wrap all elements, except first if not necessaryve işaretleyin Force split, even if line shorter than maximum line width.


Hey, bunun dışında iyi görünüyor, bunu da varsayılan indendasyon veya sütun veya 1 ile girintiye çıkarmak zorunda kaldım. Bu mantıklı değil. Girintim akıma göre farklılık gösteriyor. Örneğin: final List <DataRow> gün = MappedSelect.query ("gameDays", DataRow.class) .param ("seasonId", 20142015) .select (bağlam); Yukarıdakiler için, sonraki 2 satırın tam olarak önceki satır noktasında girintili olmasını istiyorum.
Saravana Kumar M

1
Neredeyse mükemmel! :-) Ancak bazen benim tercihime göre çok fazla sarılıyor: Lambda içindeki ifadeler, örneğin .filter(c -> c.getValue().equals(newValue)).equals'dan hemen önce sarılır. Böyle bir ayar sadece lambda ile ilgili yöntem için geçerli olsaydı ne güzel olurdu; Bunun uygulanmasının zor olabileceğini görüyorum ...
Dominic

24

Eclipse (Mars), lambda ifadeleri biçimlendiricisi için bir seçeneğe sahiptir.

Git Window > Preferences > Java > Code Style > Formatter

görüntü açıklamasını buraya girin

Click Editdüğmesine, gidin BracesEtiketi ve set Lambda BodyiçinNext Line Indented

görüntü açıklamasını buraya girin

Diğer bir seçenek de bu özellikleri proje ayarlarınıza güncellemektir. ( 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
bu yalnızca köşeli parantezli lambdalara yardımcı olur.
Nick

bu özelliklerin güncellenmesi yardımcı olmuyor
Piotr Wittchen

19

Bu soru artık eski ve ne yazık ki, Eclipse biçimlendiricinin varsayılan yapılandırması, işlevsel kodu okunabilir bir şekilde yazmak için hala kullanıcı dostu değil.

Diğer tüm cevaplarda bahsedilen her şeyi denedim ve çoğu kullanım durumu için hiç kimse uygun değil.
Bazıları için iyi, diğerleri için tatsız olabilir.

Çoğu zaman bana uyan bir yol buldum.
Başkalarına yardım edebileceğini düşünerek paylaşıyorum.

Benim yolumun bir değiş tokuşu olduğunu unutmayın: her nitelikli çağrının her zaman farklı bir çizgide olmasını kabul etmek.
Biçimlendirici yapılandırmasında eksik seçenek olabilir: 1varsayılan olarak çağrı kullanmak yerine satırı kaydırmak için çağrılar açısından eşiği belirtmek .

İşte oldukça doğru bir şekilde işlemek için 2 kombine aracım:

  • Çoğu durumda Eclipse formatlayıcı yapılandırmasını özelleştirme

  • //@formatter:off ... //@formatter:onKöşe vakalar için bir kod şablonu oluşturma .


Eclipse formatlayıcı yapılandırmasını özelleştirme
Değiştirilecek değer, yakalamada kırmızı ile çevrilidir.

Adım 1) Kendi Java Kod Stili Biçimlendiricinizi oluşturun

Preferencesmenü ve ağaçta gidin Java -> Code Style -> Formatter.
Yeni bir tane oluşturmak için "Yeni" ye tıklayın Profile("Java kuralları" ile başlatın).

Eclipse formatlayıcı

Özel biçimlendirici profilinizde sonraki iki adımın gerçekleştirilmesi gerekir.

Adım 2) Sarılı satırlar için girinti yapılandırmasını değiştirin

Kimlik yapılandırması

Değişiklik, tablolar yerine beyaz boşlukların kullanılmasına izin verir.
Satır kaydırma politikasını sütun girintisi seçeneğiyle yapılandırdığımız için sonraki adımda önemli olacaktır.
Gerçekten de hoş olmayan alanlar yaratmasını önleyecektir.

Adım 3) Kaydırılmış satırlar için varsayılan girintiyi ve şartlı çağrı için satır kaydırma politikasını değiştirin

Sarılmış çizgi boyutu


İşte sorunun kodunu içeren bir test biçimlendirmesi.

Biçimlendirmeden önce:

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

Biçimlendirmeden sonra:

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:onKöşe kasalar için kod şablonları oluşturma .

El ile yazmak veya kopyala yapıştır //@formatter:onve //@formatter:offnadiren yazdığınız için sorun yok.
Ancak haftada birkaç kez veya gün geçtikçe daha da kötüsü yazmak zorunda kalırsanız, daha otomatik bir yol kabul edilebilir.

Adım 1) Java Editor şablonuna gidin

Preferencesmenü ve ağaçta gidin Java ->Editor -> Template.
görüntü açıklamasını buraya girin

Adım 2) Seçili kod için biçimlendirmeyi devre dışı bırakmak için şablon oluşturun

Şablon Biçimlendirici kapalı

Şimdi test edebilirsiniz.
Biçimlendirmeyi devre dışı bırakmak istediğiniz satırları seçin.
Şimdi ctrl+spaceiki kez girin (birincisi "Java önerileri" ve ikincisi "şablon önerileri").
Şöyle bir şey almalısınız:

şablon önerisi

fmtŞablonu ekran görüntüsündeki gibi seçin ve "Enter" tuşuna tıklayın. Bitti!

şablon uygulamasından sonraki sonuç


16

Fonksiyonların arkasına boş yorum "//" ekleyerek tek satırlı ifadeyi biçimlendiriyorum.

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

3
Kolay ve etkili.
Steve

12
Bir IDE tarzı konfigürasyon ayarlamadığınız için kod tabanınızda gürültü olduğunu düşünüyorum. Kod tabanınıza ilk kez bakan insanlar için kafa karıştırıcı olabilir.
Marc Bouvier

9

İdeal değil, ancak formatlayıcıyı sadece biraz yoğun olan bölümler için kapatabilirsiniz. Örneğin

  //@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

"Pencere> Tercihler> Java> Kod Stili> Biçimlendirici" seçeneğine gidin. "Düzenle ..." düğmesini tıklayın, "Kapalı / Açık Etiketler" sekmesine gidin ve etiketleri etkinleştirin.


3
Bu, biçimlendirmemi düzeltmek için tuhaf ama daha basit bir seçenek gibi görünüyordu
smc

2

Benim için çalışan Never join already wrapped linesseçenek, Tercihler'de Biçimlendiricinin Satır Kaydırma bölümündeki seçeneği işaretlemekti .


1

Halihazırda özel bir Eclipse biçimlendiriciniz yoksa:

Eclipse tercihleri ​​Java> Kod Stili> Biçimlendirici Yeni Bir ad girin Tamam'a tıklayın Satır sonlarını kontrol edin

Profili düzenleyin Satır kaydırma sekmesi "Önceden sarılmış satırları asla birleştirmeyin" seçeneğini işaretleyin

Böyle bitecek

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

Her yazmanız gerekiyor. sonraki satırdan başla

krediler - https://www.selikoff.net/2017/07/02/eclipse-and-line-wrapping/


-1

Eclipse'in son sürümü yerleşik bir biçimlendiriciye sahiptir java 8 biçimlendirmesi, goto

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

and Select Eclipse 2.1[built-in] profile
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.