refactoring mit stream

guguli

Bekanntes Mitglied
Hallo,

ich möchte gerne durch Anwendung von java8 stream meinen Code etwas refactorn.

So das ist mein Code jetzt:

Code:
List<BaumElementDTO> baum = new ArrayList<>();
ErklaerungList<?> elist = ErklaerungList.create(fall.getErklaerungenAlle());
for (Gruppe<ByArtPersG> groupArtPersG : elist.groupByJahr().erklaerungen(jahr).groupByStichtagArt()
               .erklaerungen(sa).groupByArtPersG()) {
        if (groupArtPersG.merkmal().isGesellschafter()) {
               BaumKnotenDTO letzteWurzel = new BaumKnotenDTO("Gesellschaft",
                       groupArtPersG.merkmal().getArtPersG());
               baum.add(letzteWurzel);
       }
}


das hier ist ein teil davon, und die die Methoden der Klassen "ErklaerungListund", "Gruppe" sollten durch Anwendung von Stream aus ihren Klassen verschwinden, sodass diese Klassen gelöscht werden können.

Kann mir einer dabei helfen?
Danke
 
Wenn ich richtig verstehe, möchtest du z.B. diese Methodenaufrufe: elist.groupByJahr().erklaerungen(jahr).groupByStichtagArt().erklaerungen(sa).groupByArtPersG() durch sinnvolle Anwendung von Streams ersetzen?



Vielleicht ist es auch einfacher, wenn du einmal völlig unabhängig von Code erklärst, was der Algorithmus machen soll?
 
Best guess

Java:
List<BaumElementDTO> baum = ErklaerungList.create(fall.getErklaerungenAlle()).stream()
.filter(element -> element.getJahr() == jahr)
.filter(element -> element.getStichArt().equals(sa))
.filter(element -> element.merkmal().isGesellschafter())
.sort(Comparator.comparing(Erklaerung::getArtPersG))
.map(element -> new BaumKnotenDTO("Gesellschaft", element.merkmal().getArtPersG()))
.collect(Collectors.toList());
 
Wenn ich richtig verstehe, möchtest du z.B. diese Methodenaufrufe: elist.groupByJahr().erklaerungen(jahr).groupByStichtagArt().erklaerungen(sa).groupByArtPersG() durch sinnvolle Anwendung von Streams ersetzen?

genau, und ich möchte durch die Anwendung geeignten stream methoden wie groupingby sowas wie
Code:
.groupByJahr().erklaerungen(jahr).groupByStichtagArt().erklaerungen(sa).groupByArtPersG()
auflösen.
 
Klassen wie GruppeList, ErklaerungList und Gruppe sind hilfsklassen, die wurden vor java 8 verwendet, die Hoffnung ist, diese mittels Stream Methoden aufzulösen.
 
Du bist lustig - du musst die natürlich an die vorhandenen Methoden (die du uns ja nicht gezeigt hast) anpassen. Wenn man nach Jahr gruppieren kann, wird man ja irgendwie dran kommen
 
aso, in der Klasse ByJahr ist eine Methode "gruppiere": wie folgt implementiert:

Code:
public final class ByJahr {
   private ByJahr() {  
   }  
   public static SortedMap<Integer, List<Erklaerung>> gruppiere(List<Erklaerung> erklaerungen) {    
       List<Erklaerung> erklaerungenCpy = new ArrayList<>(erklaerungen);
       SortedMap<Integer, List<Erklaerung>> erklaerungenNachJahr = new TreeMap<>(Collections.reverseOrder());
       Collections.sort(erklaerungenCpy, Collections.reverseOrder(Erklaerung.SORT_BY_STICHDATUM_EINGANG));     
        for(Erklaerung erklaerung : erklaerungenCpy){
           int jahr = DateUtil.getJahr(erklaerung.getHeader().getStichdatum());
           List<Erklaerung> erklaerungenFuerEinJahr = erklaerungenNachJahr.get(jahr);
           if(erklaerungenFuerEinJahr==null){
               erklaerungenFuerEinJahr = new ArrayList<>();
               erklaerungenNachJahr.put(jahr, erklaerungenFuerEinJahr);
           }
           erklaerungenFuerEinJahr.add(erklaerung);
        }
       return erklaerungenNachJahr;
   }
}

wie kann ich .filter(element -> element.getJahr() == jahr) anpassen?
 
für "stichTagArt" gibt es in der Klasse "ErklaerungList<T>" folgende Methoden:
Java:
public GruppeList<ByStichtagArt> groupByStichtagArt() {
       SortedMap<ByStichtagArt, List<Erklaerung>> erklaerungenStichtagArt = ByStichtagArt.gruppiere(this);
       return new ErklaerungList<ByStichtagArt>(erklaerungenStichtagArt).groups();
   }

public GruppeList<T> groups() {
       GruppeList<T> result = new GruppeList<>();
       for (Entry<T,List<Erklaerung>> entry : groupByT.entrySet()) {
           result.add(new Gruppe<T>(entry.getKey(), new ErklaerungList<>(entry.getKey(), entry.getValue())));
       }
       return result;
   }


und in der Klasse "ByStichtagArt" folgende Methode
Java:
public static SortedMap<ByStichtagArt, List<Erklaerung>> gruppiere(List<Erklaerung> erklaerungenByJahr) {
       SortedMap<ByStichtagArt, List<Erklaerung>> result = new TreeMap<>();

       // group list elements
       for (Erklaerung erklaerung : erklaerungenByJahr) {
           // this is the grouping criteria
           ByStichtagArt key = new ByStichtagArt(erklaerung.getHeader().getStichdatumDisplay(),
                   erklaerung.getHeader().getBilanzart());

           // fetch elements of the group
           List<Erklaerung> bilsOfYear = result.get(key);

           if (bilsOfYear == null) {
               // no elements found
               // create new element for year and put it into result
               bilsOfYear = new ArrayList<>();
               result.put(key, bilsOfYear);
           }

           bilsOfYear.add(erklaerung);
       }

       return result;
   }


wie kann ich nun das für StichtagArt anpassen?
 
Zuletzt bearbeitet von einem Moderator:
Es sieht als würdest du mit JPA arbeiten und du versuchst neue Objekte per Liste zu erstellen und in die DB einzufügen. Warum machst du nicht einfach
Insert into ... Select... und lässt dieses ganze inperformate Objektkegelei sein?
 
Es sieht als würdest du mit JPA arbeiten und du versuchst neue Objekte per Liste zu erstellen und in die DB einzufügen. Warum machst du nicht einfach
Insert into ... Select... und lässt dieses ganze inperformate Objektkegelei sein?
Wie kommst du da auf JPA? 😵
Das ist doch ein ganz einfacher Fall von "ich habe eine Liste und möchte bestimmte Elemente daraus"...
 
Ich möchte das ganze mittels stream umschreiben. Das finde ich aber nicht so einfach.
Es geht, aber das ganze so häppchenweise zu sehen macht es für helfende etwas schwerer...


Möglicherweise ist es einfacher, die Anforderung einmal Normalsprachlich zu formulieren und dann neu mit Streams umzusetzen, ohne den alten Code zu refactoren.

Ansonsten: Zieh aus den Methoden die Bedingungen raus, damit ist dann schon mal ein vernünftiger Anfang gemacht.
 
Das GroupBy-Zeug wird anscheinend ja nur zum Filtern verwendet, d. h. Du kannst alles einfach durch filter() ersetzen. In dem Fall werden einfach zwei Werte benötigt:
erklaerung.getHeader().getStichdatumDisplay() und erklaerung.getHeader().getBilanzart().

Ich hab das so gemacht, bekomme aber eine fehlermeldung:
Code:
.filter(element -> new ByStichtagArt(element.getHeader().getStichdatumDisplay(), element.getHeader().getBilanzart()))

Type mismatch: cannot convert from ByStichtagArt to boolean

ich muss das irgendwie ohne die klasse ByStichtagArt machen oder ?!
 
Müssen tust Du gar nichts 🙂

Du hast zum Vergleich "sa" gegeben - von welchem Typ ist der und wie sieht der Typ aus?
 
Was ich aus den Häppchen weiß...
Es gibt eine Klasse, die Beispielsweise Fall heißt, diese besitzt eine Liste an Erklaerungen.
Code:
------------------------------------------------
Fall
------------------------------------------------
- erklaerungen: List<Erklaerung>
------------------------------------------------
+ getErklaerungenAlle(): List<Erklaerung>
------------------------------------------------

Eine Erklaerung hat mindestens einen Header
Code:
------------------------------------------------
Erklaerung
------------------------------------------------
- header: Header
------------------------------------------------
+ getHeader(): Header
------------------------------------------------

Und der Header hat vermutlich mindestens das:
Code:
------------------------------------------------
Header
------------------------------------------------
- stichdatum: Date
- bilanzart: String
------------------------------------------------
+ getStichdatumDisplay(): String
+ getBilanzart(): String
------------------------------------------------

Wobei das Display vermutlich nur eine StringFormatierung des Datums ist und Bilanzart auch nochmal irgendeine andere Klasse oder Enum etc sein könnte.

Was noch nicht bekannt ist sind die Merkmale mit den Gesellschaftern.

Du möchtest die Liste der Erklärungen eines Falls...
1. Nach dem Jahr der Erklärung filtern
2. Nach Stichtagart filtern, was eine Verknüpfung aus dem Displaywert und der Bilanzart ist.
3. Nach dem Merkmal Gesellschafter filtern

Hier ein mein Best Guess ein bissl angepasst:
Java:
List<BaumElementDTO> baum = fall.getErklaerungenAlle().stream()
.filter(erklaerung -> DateUtil.getJahr(erklaerung.getHeader().getStichdatum()) == jahr)
.filter(erklaerung -> erklaerung.getHeader().getStichdatumDisplay.equals(display))
.filter(erklaerung -> erklaerung.getHeader().getBilanzart().equals(art))
.filter(erklaerung -> erklaerung.getMerkmal().isGellschaft())
.map(erklaerung -> new BaumKnotenDTO("Gesellschaft", erklaerung.merkmal().getArtPersG()))
.collect(Collectors.toList());

Und ganz nebenbei war die ganze Sache auch schon vor Java 8 umständlicher als nötig.
 
danke @MoxxiManagarm das geht glaube ich in richtigen Richtung, ich poste jetzt den kompletten Methode. Die For schleife muss sozusagen durch stream ersetzt werden.

Code:
public HoleBilanzResponseDTO run(HoleBilanzRequestDTO request) {
       Long erklId = request.getErklId();
       this.zusatzKnotenOptional = request.getKontext() == null ? null : request.getKontext().getZusatzKnoten();

       Fall fall = EBContext.get().getFall(erklId);

       Erklaerung erklaerung = fall.getHauptErklaerung();
       HoleBilanzResponseDTO result = new HoleBilanzResponseDTO();
       result.setErklId(erklId);

       // Bereite Vorjahrevorhandenmerker auf
       String vorjahre = "";
       for (Erklaerung vorjahr : erklaerung.getVorjahre()) {
           if (vorjahr == null) {
               vorjahre = vorjahre.concat("2");
           } else {
               vorjahre = vorjahre.concat("1");
           }
       }

       // Bereite WeitereStichtagemerker auf
       boolean hatWeitereStichtage = erklaerung.getHatWeitereStichtage();
       BaumDisplayer bilanzDisplayer = new BaumDisplayer(erklaerung, vorjahre, hatWeitereStichtage,
               zusatzKnotenOptional);

       List<BilanzElementDTO> bilanzElemente = bilanzDisplayer.display();

       if (fall.isVersionskonfliktErklaerungen()) {
           throw new EBException(fall.getVersionskonfliktErklaerungenFehlertext());
       }

       EBContext.get().setSelectedErklId(request.getErklId());
       if ("ab".equals(request.getReihenfolgeVJ())) {
           EBContext.get().setStichtagAbsteigendSortieren(true);
       }

       String stichtagString = erklaerung.getHeader().getStichdatumDisplay();

       String arbeitsbereich = erklaerung.getHeader().getArbeitsbereich();

       // Titel erstellen
       result.setName(erklaerung.getHeader().getName());
       result.setGesellschaftsform(fall.getGesellschaftsform().getName());
       // String stnr = EBContext.get().getSteuernummer();

       result.setSteuernummer(fall.getBezeichnerStnr());
       result.setFenstertitel(
               " " + ((arbeitsbereich == null || arbeitsbereich.isEmpty()) ? "" : ("/ " + arbeitsbereich + " "))
                       + erklaerung.getHeader().getName() + " - E-Bilanz " + stichtagString);

       BilanzartSteuerlich bilanzartSteuerlichEnum = erklaerung.getHeader().getBilanzartSteuerlich();
       if (bilanzartSteuerlichEnum != null) {
           result.setArtpersg(bilanzartSteuerlichEnum.getValue());
       }

       // Bei Personengesellschaften sind ggf. vorhandene Sonder-/
       // Ergänzungsbilanzen
       // (für Gesellschafter 1..n) anzuzeigen:
       List<BaumElementDTO> baumSonderErgaenzBil = new ArrayList<>();
       String stichtag = StichtagUtil.dateToAufbereitetString(erklaerung.getHeader().getStichdatum());
       Integer jahr = erklaerung.getHeader().getStichdatum().getYear() + 1900;
       ByStichtagArt sa = new ByStichtagArt(stichtag, erklaerung.getHeader().getBilanzart());

       ErklaerungList<?> elist = ErklaerungList.create(fall.getErklaerungenAlle());
       for (Gruppe<ByArtPersG> groupArtPersG : elist.groupByJahr().erklaerungen(jahr).groupByStichtagArt()
               .erklaerungen(sa).groupByArtPersG()) {
           // Nur wenn Sonder-/Ergänzungsbilanz :
           if (groupArtPersG.merkmal().isGesellschafterSonderErgaenzungsbilanz()) {
               BaumKnotenDTO letzteWurzel = new BaumKnotenDTO("Gesellschaftergruppe",
                       groupArtPersG.merkmal().getArtPersG());
               baumSonderErgaenzBil.add(letzteWurzel);
               // Gesellschafterschleife :
               for (Gruppe<ByGesellschafterUndArtPersG> groupGesellschafterArtPersG : groupArtPersG.erklaerungen()
                       .groupByGesellschafterUndArtPersG()) {
                   String gesLabel = groupGesellschafterArtPersG.merkmal().getLabel();
                   BaumKnotenDTO gesellschafterWurzel = new BaumKnotenDTO("Gesellschafternr", gesLabel);
                   letzteWurzel.addElement(gesellschafterWurzel);
                   // Bilanz-Schleife
                   for (Erklaerung e : groupGesellschafterArtPersG.erklaerungen().sortByEingangsdatum()) {
                       gesellschafterWurzel.addElement(new BaumBlattDTO(e));
                   }
               }
           }
       }

       BaumElementDTO root;
       if (erklaerung.getHeader().isGesamthandsbilanz()) {
           root = new BaumKnotenDTO("ArtPersG", BilanzartSteuerlich.GESAMTHANDSBILANZ.getValue());
           BaumBlattDTO bb = new BaumBlattDTO(erklaerung);
           ((BaumKnotenDTO) root).addElement(bb);
           bb.getChildren().addAll(bilanzElemente);
           result.getBaumelemente().add(root);
           result.getBaumelemente().addAll(baumSonderErgaenzBil);
       } else {
           root = new BaumBlattDTO(erklaerung);
           root.getChildren().addAll(bilanzElemente);

           result.getBaumelemente().add(root);
       }

       // Ist die Erkl von jmd. anders bereits in Bearbeitung?
       KontextDTO kontext = (KontextDTO) EBContext.get().getAufrufkontext();
       if (kontext != null && kontext.isBearbeitungEnabled() && kontext.getAufrufquelle() == Aufrufquelle.EBBearbeitung
               && kontext.isBearbeitungAbgelehnt(erklId)) {
           NachrichtDTO nachricht = new NachrichtDTO();
           SperreDTO s = kontext.getSperre(erklId);
           nachricht.setText("EBilanz nur lesende Anzeige möglich.\n" + (s == null ? "" : s.getHinweistext()));
           nachricht.setTyp(NachrichtTyp.HINWEIS);
           result.setNachricht(nachricht);
       }

       return result;
   }

getHeader ist in der klasse Erklearung und gibt ein Objekt der Klasse Heaser zurück.

Die kLasse Erklearung liste ist wie folgt:
Code:
public class ErklaerungList<T> extends ArrayList<Erklaerung> {

   private static final long serialVersionUID = 1L;
   private SortedMap<T, List<Erklaerung>> groupByT=  new TreeMap<>();
   
   public ErklaerungList(T gruppe, List<Erklaerung> erklaerungen) {
       super(Collections.unmodifiableList(new ArrayList<Erklaerung>(erklaerungen)));   
       groupByT.put(gruppe, erklaerungen);
   }
   
   private ErklaerungList(SortedMap<T, List<Erklaerung>> groupByT) {
       super(getErklaerungen(groupByT));
       this.groupByT = groupByT;
   }

   public List<Erklaerung> asList() {
       return getErklaerungen(groupByT);
   }
   
   private static <T> List<Erklaerung> getErklaerungen( Map<T, List<Erklaerung>> xxx) {
        List<Erklaerung> result = new ArrayList<>();
        for (List<Erklaerung> v : xxx.values()) {
            result.addAll(v);
        }
        return result;
   }
   
   public GruppeList<T> groups() {
       GruppeList<T> result = new GruppeList<>();
       for (Entry<T,List<Erklaerung>> entry : groupByT.entrySet()) {
           result.add(new Gruppe<T>(entry.getKey(), new ErklaerungList<>(entry.getKey(), entry.getValue())));
       }
       return result;
   }
   
   
   public static ErklaerungList<?> create(List<Erklaerung> erklaerungen) {
       return new ErklaerungList<>("NOGROUP", erklaerungen);
   }
   

   public GruppeList<Integer> groupByJahr() {
       SortedMap<Integer, List<Erklaerung>> erklaerungenNachJahr = ByJahr.gruppiere(this);       
       return new ErklaerungList<Integer>(erklaerungenNachJahr).groups();
   }

   public GruppeList<ByStichtagArt> groupByStichtagArt() {
       SortedMap<ByStichtagArt, List<Erklaerung>> erklaerungenStichtagArt = ByStichtagArt.gruppiere(this);
       return new ErklaerungList<ByStichtagArt>(erklaerungenStichtagArt).groups();
   }

   public GruppeList<ByArtPersG> groupByArtPersG() {
       return groupByArtPersG(ByArtPersG.GESELLSCHAFTER_GROUPSIZE, ByArtPersG.GESELLSCHAFTER_MAXGROUPS);
   }

   public GruppeList<ByArtPersG> groupByArtPersG(int groupSize, int maxGroups) {
       SortedMap<ByArtPersG, List<Erklaerung>> erklaerungenArtPersG = ByArtPersG.gruppiere(this, groupSize, maxGroups);
       return new ErklaerungList<ByArtPersG>(erklaerungenArtPersG).groups();
   }
   
   public GruppeList<ByGesellschafterUndArtPersG> groupByGesellschafterUndArtPersG() {
       SortedMap<ByGesellschafterUndArtPersG, List<Erklaerung>> erklaerungenGesellschafterUndArtPersG = ByGesellschafterUndArtPersG.gruppiere(this);
       return new ErklaerungList<ByGesellschafterUndArtPersG>(erklaerungenGesellschafterUndArtPersG).groups();
   }
   

   
   public ErklaerungList<T> sortByEingangsdatum() {
       Collections.sort(this, Erklaerung.SORT_BY_EINGANGSDATUM);
       return this;
   }   
   
}
 
Mein Ansatz sollte aufzeigen, dass ich versucht habe die Anforderung neu zu formulieren. Gehe gedanklich von all den Helfermethoden und -klassen weg, welche du bedenkenlos raushauen kannst. Male dir deine wichtigen Komponenten als klassendiagramm auf. Dann hast du die Beziehungen und Struktur. Mit der Klarheit, welche du dir so schaffst wirst du den Stream bestimmt ohne Mühe selbst korrekt formulieren können. Die Helfer waren bereits vor java 8 umständlicher als nötig und verwirren jetzt nur noch umso mehr. Hau sie weg und machs neu.
 
I habe das soweit fertig:

Java:
baumSonderErgaenzBil = fall.getErklaerungenAlle2().stream()
               .filter(element -> DateUtil.getJahr(element.getHeader().getStichdatum()) == jahr)
               .filter(element -> element.getHeader().getStichdatumDisplay().equals(StichtagUtil.dateToAufbereitetString(erklaerung.getHeader().getStichdatum())))
               .filter(element -> element.getHeader().getBilanzart().equals(sa.getArt()))
               .filter(element -> element.getHeader().getBilanzartSteuerlich().equals(bilanzartSteuerlichEnum.getValue()))
               .collect(Collectors.toList());

nun will ich die if statement umschrieben. so wie oben beshrieben mit getMerkmal() kann ich nicht, denn getMerkmal() exitiert nirgendwo.

Java:
if (groupArtPersG.merkmal().isGesellschafterSonderErgaenzungsbilanz()) {
               BaumKnotenDTO letzteWurzel = new BaumKnotenDTO("Gesellschaftergruppe",
                       groupArtPersG.merkmal().getArtPersG());
               baumSonderErgaenzBil.add(letzteWurzel);
               // Gesellschafterschleife :
               for (Gruppe<ByGesellschafterUndArtPersG> groupGesellschafterArtPersG : groupArtPersG.erklaerungen()
                       .groupByGesellschafterUndArtPersG()) {
                   String gesLabel = groupGesellschafterArtPersG.merkmal().getLabel();
                   BaumKnotenDTO gesellschafterWurzel = new BaumKnotenDTO("Gesellschafternr", gesLabel);
                   letzteWurzel.addElement(gesellschafterWurzel);
                   // Bilanz-Schleife
                   for (Erklaerung e : groupGesellschafterArtPersG.erklaerungen().sortByEingangsdatum()) {
                       gesellschafterWurzel.addElement(new BaumBlattDTO(e));
                   }
               }
           }
 
Zuletzt bearbeitet von einem Moderator:
I habe das soweit fertig:
Hm... ich hätte jetzt etwas wie
Java:
Map<BilanzSteuerlich, List<Erklaerung>> erklaerungen = fall.getErklaerungenAlle().stream()
    .filter(erklaerung -> DateUtil.getJahr(erklaerung.getHeader().getStichdatum()) == jahr)
    .filter(erklaerung -> erklaerung.getHeader().getStichdatumDisplay.equals(display))
    .filter(erklaerung -> erklaerung.getHeader().getBilanzart().equals(art))
    .filter(erklaerung -> erklaerung.getMerkmal().isGellschaft())
    .collect(Collectors.groupingBy(erklaerung -> erklaerung.getMerkmal().getArtPersG()));
erwartet.
 

Neue Themen


Zurück
Oben