Home java Stream API Java Comparator

Stream API Java Comparator

Author

Date

Category

In front of me there is a task: in SortConfig configured on the XML configuration. For example:

& lt; xml version = "1.0" encoding = "UTF-8"? & gt;
& lt; sort-criterias & gt;
  & lt; Name Order = "ASC" / & gt;
  & lt; Price Order = "ASC" / & gt;
  & lt; rate Order = "DESC" / & GT;
& lt; / sort-criterias & gt;

I need to sort first by name, then only the price and at the end by rating. But my method all put up on the head! According to the result, the main criterion of sorting, he takes the last line of configuration. I need to fix it. I know that you can correctly sort by sort (compararator.thencomparing (...). Thencomparing (...)) But I can not even imagine how! Help PJ ((I will be immensely grateful

Listing classes above:

Public Class CombinedProductomparator Implements Compararator & LT; Product & GT; {
  Private Final String FieldName;
  Private Final Order Order;
  Public CombinedProductcomparator (String FieldName, Order Order) {
    this.fieldName = FieldName;
    this.Order = order;
  }
  @Override
  Public int COMPARE (Product O1, Product O2) {
    Comparator & lt; Product & GT; Comparator;
    Switch (FieldName) {
      CASE "NAME":
        Comparator = New ProductNameComparator ();
        Break;
      Case "Price":
        Comparator = new productpricecomparator ();
        Break;
      Default:
      CASE "RATE":
        Comparator = New ProductrateComparator ();
    }
    if (Order == Order.Desc) compararator = compararator.Reversed ();
    Return compararator.compare (O1, O2);
  }
}
@ data
@Noargsconstructor
Public Class SortConfig {
  Private String FieldName;
  Private Order Order;
  Public SortConfig (String FieldName, Order Order) {
    this.fieldName = FieldName;
    this.Order = order;
  }
}
Public Class Catalog Implements Serializable {
  @Getter.
  @Setter.
  Private List & LT; Category & GT; Categories;
}
@ data
Public Abstract Class Category Implements Serializable {
  Protected String Title;
  PROTECTED LIST & LT; Product & GT; Products;
  @Override
  Public Boolean Equals (Object O) {
    if (this == o) Return True;
    if (O == NULL || getClass ()! = O.Getclass ()) Return False;
    Category Category = (Category) O;
    Return title.equals (Category.title);
  }
  @Override
  Public int hashcode () {
    Return Objects.hash (Title);
  }
}
@ data
@Noargsconstructor
Public Class Product IMPLEMENTS SERIALIZABLE {
  Private String Name;
  Private Long Priceincents;
  Private int rarate;
  Public Product (String Name, Long Preincents, Int Rate) {
    this.name = Name;
    this.priceincents = PriceinCents;
    this.rate = rate;
  }
}

can of course do this:

Public Catalog SortCatalog (Catalog Catalog, String ConfigPath) {
    CATALOG SORTEDCATALOG = CLONECATALOG (CATALOG);
    List & lt; SortConfig & GT; SortConfig = SortService.getConfigList (ConfigPath);
    For (Category Category: sortedcatalog.getcategories ()) {
      Category.setProducts (Category.getProducts (). Stream ()
          .Sorted (SortConfigComparator (SortConfig.get (0) .GetFieldName (), SortConfig.get (0) .GetOrder ())
          .Thencomparing (SortConfigComparing (SortConfig.get (1) .GetFieldName (), SortConfig.get (1) .GetOrder ()))
          .thencomparing (SortConfigComparing (SortConfig.get (2) .GetFieldName (), SortConfig.get (2) .GetOrder ())))
          .collect (collectors.tolist ()));
    } 
Return sortedcatalog;
  }

but what if sort-config.xml will have a variable number of sorting parameters?


Answer 1, Authority 100%

Create a comparator something like this:

compararator & lt; Product & gt; Combined = NULL;
For (SortConfig SortConfig: SortService.getConfigList (ConfigPath)) {
  If (Combined == NULL) {
    Combined = New CombinedProductComparator (
sortconfig.getfieldname (), sortconfig.getOrder ());
  } else {
    Combined = Combined.Thencomparing (
       New CombinedProductComparator (
          sortconfig.getfieldname (), sortconfig.getOrder ()));
  }
}

or option with Reduce :

compararator & lt; Product & gt; Combined = SortService.getConfigList (ConfigPath)
 .stream ()
 .map (SortConfig - & gt; new CombinedProductComparator (
     SortConfig.getFieldName (), SortConfig.getOrder ()))
 .reduce (NULL, (CombinedSofar, NextComparator) - & gt;
   (CombinedSofar == NULL)? NextComparator: CombinedSofar.Thencomparing (NextComparator)
});

Well, then use the composite comparator for sorting:

productstream = productstream.sorted (Combined);

Answer 2

recovered, it turned out like this:

list & lt; compararator & lt; product & gt; & gt; Comparators = SortService.getConfigList (ConfigPath)
        .stream ()
        .map (S - & GT; new CombinedProductComparator (S.GetFieldName (), S.GetOrder ()))
        .collect (collectors.tolist ());
    Comparator & lt; Product & GT; CombinedComparator = comparators.stream ()
        .reduce (NULL, COMP1, COMP2) - & GT; {
          if (comp1 == null) {
            RETURN COMP2;
          } else {
            Return comp1.thencomparing (comp2);
          }
        });
    CATALOG SORTEDCATALOG = CLONECATALOG (CATALOG);
    sortedcatalog.setcategories (sortedcatalog.getcategories (). Stream ()
        .peek (C - & GT; C.getProducts (). Sort (CombinedComparator))
        .collect (collectors.tolist ()));
    Return sortedcatalog;

Thank you @RonaNGonoval!

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions