-1

I have the following query that I would like to convert to use on the List class that I have. The goal is to convert it to java 8 lambda. The main problem I am facing is to get "trademinuessincemidnight and paper" to be output to the new List

The AssetTotals class will of course contain the 4 output fields with accessors (price, countPapers, paper, trademinutessincemidnight).

SELECT avg(price), count(price), paper, TRADEMINUTESSINCEMIDNIGHT FROM sgdata.ASSET group by TRADEMINUTESSINCEMIDNIGHT, paper order by paper, TRADEMINUTESSINCEMIDNIGHT

public class Asset implements Serializable, Comparable<Asset> {

    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id; // still set automatically

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    long sequenceNo;
    String Exchange;
    String Board;
    long time;
    String paper;
    long tradeTime;
    long quantity;
    double price;
    String source;
    String buyer;
    String seller;
    float changeSinceLast;
    String initator;
    long tradeTimeSinceMidnight;
    long tradeMinutesSinceMidnight;
    long daysSinceEpoch;


    public long getSequenceNo() {
        return sequenceNo;
    }
    public void setSequenceNo(long sequenceNo) {
        this.sequenceNo = sequenceNo;
    }
    public String getExchange() {
        return Exchange;
    }
    public void setExchange(String exchange) {
        Exchange = exchange;
    }
    public String getBoard() {
        return Board;
    }
    public void setBoard(String board) {
        Board = board;
    }
    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    public String getPaper() {
        return paper;
    }
    public void setPaper(String paper) {
        this.paper = paper;
    }
    public long getTradeTime() {
        return tradeTime;
    }
    public void setTradeTime(long tradeTime) {
        this.tradeTime = tradeTime;
    }
    public long getQuantity() {
        return quantity;
    }
    public void setQuantity(long quantity) {
        this.quantity = quantity;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getBuyer() {
        return buyer;
    }
    public void setBuyer(String buyer) {
        this.buyer = buyer;
    }
    public String getSeller() {
        return seller;
    }
    public void setSeller(String seller) {
        this.seller = seller;
    }
    public float getChangeSinceLast() {
        return changeSinceLast;
    }
    public void setChangeSinceLast(float changeSinceLast) {
        this.changeSinceLast = changeSinceLast;
    }
    public String getInitator() {
        return initator;
    }
    public void setInitator(String initator) {
        this.initator = initator;
    }

    public long getDaysSinceEpoch() {
        return daysSinceEpoch;
    }
    public void setDaysSinceEpoch(long daysSinceEpoch) {
        this.daysSinceEpoch = daysSinceEpoch;
    }
    public long getTradeTimeSinceMidnight() {
        return tradeTimeSinceMidnight;
    }
    public void setTradeTimeSinceMidnight(long tradeTimeSinceMidnight) {
        this.tradeTimeSinceMidnight = tradeTimeSinceMidnight;
    }

    public long getTradeMinutesSinceMidnight() {
        return tradeMinutesSinceMidnight;
    }
    public void setTradeMinutesSinceMidnight(long tradeMinutesSinceMidnight) {
        this.tradeMinutesSinceMidnight = tradeMinutesSinceMidnight;
    }


    @Override
    public boolean equals(Object obj) {

        return sequenceNo == ((Asset)obj).sequenceNo;

    }

    @Override
    public int compareTo(Asset otherAsset) {
        if (this.getSequenceNo() < otherAsset.getSequenceNo()) {
            return -1;
        }
        else if (this.getSequenceNo() == otherAsset.getSequenceNo()) {
            return 0;
        }
        return 1;
    }
    @Override
    public String toString() {
        return this.paper + " " + this.price + " " + this.tradeMinutesSinceMidnight;

    }

}
user2130951
  • 2,601
  • 4
  • 31
  • 58
  • 3
    In most cases you're better off letting your database perform queries for you, and not attempt to retrieve more data than you need into the VM and then execute Java code to perform searching and filtering. What are you trying to do, and why? – Kevin Hooke May 04 '15 at 18:31
  • I would have done it in the database if I had the information in the database. However I am using a List in real time and adding to that. Not writing the data to the database and retrieve it's aggregates. But I know how it would look using a database that's why I wrote what it would look like. – user2130951 May 04 '15 at 18:44
  • 1
    Can you show what you've tried so far with your lambda expression? You're more likely to get answers from others if you can show how far you've got with your expression so far and then ask for specific help on one part of the expression that you can't get working rather than asking for someone to write the expression for you? – Kevin Hooke May 04 '15 at 21:40

1 Answers1

3
List<Asset> list=…;
Comparator<Asset> group=Comparator.comparing(Asset::getPaper)
                                  .thenComparing(Asset::getTradeMinutesSinceMidnight);
list.stream().collect(Collectors.groupingBy(
        Function.identity(), ()->new TreeMap<>(group),
        Collectors.summarizingDouble(Asset::getPrice)))
    .forEach((a,p)-> System.out.println(
             a.getPaper()
       +"\t"+a.getTradeMinutesSinceMidnight()
       +"\t"+p.getAverage()
       +"\t"+p.getCount()));

Since you want to group and sort by the same properties, the easiest way to achieve this is by collecting into a sorted map which uses an appropriate Comparator. The resulting map will have Asset instances as keys which have distinct tuples for these properties but you must not make any assumptions about the other properties as the key object is just one arbitrary instance picked out of the group.

The values of the map are determined by the downstream collector, which is a summarizingDouble(Asset::getPrice) collector which will produce an instance of DoubleSummaryStatistics holding all aggregated values for the price property, max, min, average, count and sum. I printed count here as requested by your question, however, I suspect, you actually want sum instead but it’s easy to change.

Compare also to this answer which also discusses the related tasks of grouping by one property and aggregating more than one property.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765