PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, November 3, 2022

[FIXED] How to use a Function<T, R> as parameter in method

 November 03, 2022     comparable, java, lambda, method-reference, methods     No comments   

Issue

I'm learning Java lambdas for school, and I am stuck for a couple of days now.

Background

I have a list of pumps which I have to sort out on power, last revision, … I already wrote a Comparator that's returning a List<Pump>:

class PowerComparator implements Comparator<Pomp> {
    @Override
    public int compare(Pump pump1 , Pump pump2) {
        return Double.compare(pump1.getPower(), pump2.getPower());
    }
}

I have to write one function that's returning a List<Pump> that can returning a sorted list (power, revision, ...) using a lambda.

The method signature is:

public List<Pump> sortedBy(Function<Pump, Comparable<Pump>> function)

I know that the Function interface is returning a Comparator, but I don't know how to use the function in it.

Below is what I already found (it's not correct). I am really stuck here.

public List<Pump> sortedBy(Function<Pump, Comparable<Pump>> function){
    List<Pump> sortBy = new ArrayList<Pump>(pumps);
    function.apply((Pump) ->Comparator.comparing(pumps::comparator));
    Collections.sort(sortBy, Comparator.comparing(function.apply(pumps);
    return sortBy;
}

Additional info (in dutch)

public class Data {

    private static List<Pomp> data;

    public static List<Pomp> getData() {
        data = new ArrayList<>();

        data.add(new Pomp("J6706A", 100.0, 2, Aandrijving.TURBINE, LocalDate.of(2022, 1, 10), true, 500.0, "Slurry pomp"));
        data.add(new Pomp("J6707A", 55.5, 1, Aandrijving.MOTOR, LocalDate.of(2022, 2, 10), false, 500.0, "Clarified pomp"));
        data.add(new Pomp("J6706B", 100.0, 2, Aandrijving.TURBINE, LocalDate.of(2022, 3, 10), true, 500.0, "Slurry pomp"));
        data.add(new Pomp("J6706C", 100.0, 2, Aandrijving.TURBINE, LocalDate.of(2022, 4, 10), true, 500.0, "Slurry pomp"));
        data.add(new Pomp("J6705A", 62, 1, Aandrijving.MOTOR, LocalDate.of(2022, 5, 10), false, 250, "Voedings pomp"));
        data.add(new Pomp("J6705B", 35, 2, Aandrijving.TURBINE, LocalDate.of(2022, 6, 10), false, 150, "Voedings pomp"));
        data.add(new Pomp("J6708B", 100.0, 2, Aandrijving.TURBINE, LocalDate.of(2022, 7, 10), false, 300, "HCO circ pomp"));

        return data;
    }

}

public class Pompen {
    private TreeSet<Pomp> pompen = new TreeSet<>();
    public void add(Pomp pomp) {
        pompen.add(pomp);
    }
 class VermogenComparator implements Comparator<Pomp> {
        @Override
        public int compare(Pomp pomp1 , Pomp pomp2) {
            return Double.compare(pomp1.getVermogen(), pomp2.getVermogen());
        }
    }
    class RevisieComparator implements Comparator<Pomp> {
        @Override
        public int compare(Pomp pomp1 , Pomp pomp2) {
            return pomp1.getLaatsteRevisie().compareTo(pomp2.getLaatsteRevisie());
        }
    }
    class Zelfontbranding implements Comparator<Pomp> {
        @Override
        public int compare(Pomp pomp1 , Pomp pomp2) {
            return Boolean.compare(pomp1.getBovenZelfOntbranding(), pomp2.getBovenZelfOntbranding());
        }
    }

Solution

Because of your example using sortBy(Pump::getName), I believe that the intent here is to use the Comparator.comparing() factory to create a comparator that extracts a sort key from each object. However, this requires some changes to the generic types used in the prescribed method signature. Working code would look something like this:

public <U extends Comparable<? super U>> List<Pomp> sortedBy(Function<Pomp, ? extends U> toKey) {
    List<Pomp> sorted = new ArrayList<>(pompen);
    sorted.sort(Comparator.comparing(toKey));
    return sorted;
}

This will accept lambdas like Pomp::getNaam as long as the indicated property is Comparable:

System.out.println("Pumps sorted on power:");
pompen.sortedBy(Pomp::getVermogen).forEach(System.out::println);

A better design would be to pass a Comparator; while it's a tiny bit more work for the caller, it gives them full control over the sorting. For example, they can specify a secondary sort key, or reverse the order. Or one could go another step further and simply return a copy of the pumps collection as a list and let the caller do whatever they wish with it.


If permitted, you could change the API to this:

public List<Pomp> sortedBy(Comparator<? super Pomp> order) {
    List<Pomp> sorted = new ArrayList<>(pompen);
    sorted.sort(order);
    return sorted;
}

The caller would then be responsible for creating a Comparator that meets their need:

/* Like this: */
List<Pomp> sortedByName = pompen.sortedBy(Comparator.comparing(Pomp::getNaam));
/* Or this: */
List<Pomp> pumpsDescendingPower = 
  pompen.sortedBy(Comparator.comparing(Pomp::getVermogen).reversed());

This approach is more idiomatic for Java.



Answered By - erickson
Answer Checked By - Terry (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing