0

I have this class

class TimeSpentStats{
  int manId;
  String sessionId;
  int userId;
  Long timeStamp;
}

I have a List and I want to get the minimum timestamp and maximum from the list for each (manId, sessionId, userId)

So for example, I have:

manId sessionId userId timeStamp

1      01F      5          1000
1      01F      5          1005
3      6Y       3           7
3      6Y       3           16

I need for (1 01F 5) -> min = 1000 , max = 1005 and for (3 6Y 3 ) - > min = 7 , max = 16

I need to add maybe 2 attributes in the same class? Any ideas if I can do this? Thank you

user3796867
  • 17
  • 1
  • 7

3 Answers3

3

If you have a List of TimeSpentStatus called list, the following algorithm should do what you want it to do.

HashMap<String, Pair> statsList = new HashMap<String, Pair>();
for(TimeSpentStats stats : list){
    // Constructs the combination of IDs that is used as the key to a Pair object
    String statsStr = stats.manId + " " + stats.sessionId + " " + stats.userId;
    if(statsList.containsKey(statsStr)){
        // Update min and/or max time for the current combination as necessary
        statsList.get(statsStr).minTime = Math.min(statsList.get(statsStr).minTime, stats.timeStamp);
        statsList.get(statsStr).maxTime = Math.max(statsList.get(statsStr).maxTime, stats.timeStamp);
    }else{
        // Construct a new Pair for the ID combination and add max and min times
        Pair p = new Pair();
        p.maxTime = stats.timeStamp;
        p.minTime = stats.timeStamp;
        // Adds the new combination to the HashMap, which can now be updated in the if-statement
        statsList.put(statsStr, p);
    }
}

statsList will now contain the max and min times for each combination with (userID + " " + manID + " " + sessionID) as the keys. You will then be able to get the Pair object for a specific combination by using statsList.get(userId + " " + manId + " " + sessionId) (as long as it exists of course).

Here is the Pair class

class Pair{
    public long minTime;
    public long maxTime;
}
SamTebbs33
  • 5,507
  • 3
  • 22
  • 44
  • Just an aside, there's no real reason to write your own `Pair` class. There are several implementations floating around you could grab, such as **org.apache.commons.math3.util.Pair**, **org.apache.commons.lang3.tuple.Pair**, or you could even just use a raw **Map.Entry**. – azurefrog Oct 13 '14 at 15:36
0

If the elements of the triple are independent, then this is a problem in combinatorics as much as anything else: you need to find all of the triples. That's a pretty well-described problem, and there are recursive solutions that Java can handle, though of course you have to watch the stack if the problem gets large. If the elements of the triple are dependent, then life is easier. In any case, the brute force approach is obvious: iterate over the comparable items and compare item to max and compare item to min. Record the max and the min. If these are in an object, then you can make a nested HashMap, for example mapping manIds to (maps of sessionIds to (maps of Userids to (max,min))) where max, min might be the object which contains the max/min value or they might be the values themselves - that's up to you and what you need. This map would be a static member of the class that these instantiate, essentially you'd be caching the maxen and the mins as the objects are created. Not too hard to see how this would go into the constructor. This adds some overhead as the problem gets large, but it spares you a lot of iteration, so it's probably a worthwhile tradeoff.

Jon Kiparsky
  • 7,499
  • 2
  • 23
  • 38
0
public class Main
{
    public static void main( String[] args )
    {
        Map< TimeSpentStats, MinMax > hashMap = new HashMap< TimeSpentStats, MinMax >();
        addToMap( hashMap, new TimeSpentStats( 1, "01F", 5, 1000L ) );
        addToMap( hashMap, new TimeSpentStats( 1, "01F", 5, 1005L ) );
        addToMap( hashMap, new TimeSpentStats( 3, "6Y", 3, 7L ) );
        addToMap( hashMap, new TimeSpentStats( 3, "6Y", 3, 16L ) );

        for ( Map.Entry< TimeSpentStats, MinMax > entry : hashMap.entrySet() )
        {
            TimeSpentStats timeSpentStats = entry.getKey();
            MinMax minMax = entry.getValue();
            System.out.println( timeSpentStats.getManId() + "\t" + timeSpentStats.getSessionId() + "\t" + timeSpentStats.getUserId() + "\tMin Time Stamp :" + minMax.getMin() + "\tMax Time Stamp :" + minMax.getMax() );
        }
    }

    private static void addToMap( Map< TimeSpentStats, MinMax > hashMap, TimeSpentStats timeSpentStats )
    {
        MinMax timeStampMinMax = hashMap.get( timeSpentStats );
        if ( timeStampMinMax != null )
            timeStampMinMax.updateValues( timeSpentStats.getTimeStamp() );
        else
            hashMap.put( timeSpentStats, new MinMax( timeSpentStats.getTimeStamp() ) );
    }
}

class MinMax
{
    private Long min;
    private Long max;

    MinMax( Long timeStamp )
    {
        this.min = timeStamp;
        this.max = timeStamp;
    }

    public Long getMin()
    {
        return min;
    }

    public Long getMax()
    {
        return max;
    }

    public boolean updateValues( Long timeStamp )
    {
        if ( timeStamp < this.min )
        {
            this.min = timeStamp;
            return true;
        }
        else if ( timeStamp > this.max )
        {
            this.max = timeStamp;
            return true;
        }

        return false;
    }
}

class TimeSpentStats
{
    private final int manId;
    private final String sessionId;
    private final int userId;
    private final Long timeStamp;

    public TimeSpentStats( int manId, String sessionId, int userId, Long timeStamp )
    {
        this.manId = manId;
        this.sessionId = sessionId;
        this.userId = userId;
        this.timeStamp = timeStamp;
    }

    public int getManId()
    {
        return manId;
    }

    public String getSessionId()
    {
        return sessionId;
    }

    public int getUserId()
    {
        return userId;
    }

    public Long getTimeStamp()
    {
        return timeStamp;
    }

    @Override
    public boolean equals( Object obj )
    {
        if ( obj instanceof TimeSpentStats )
        {
            TimeSpentStats timeSpentStats = (TimeSpentStats)obj;
            return this.manId == timeSpentStats.manId && this.sessionId.equals(timeSpentStats.sessionId) && this.userId == timeSpentStats.userId;
        }
        return false;
    }

    @Override
    public int hashCode()
    {
        return sessionId.hashCode();
    }
}

Edit : a small bug is fixed. Here I had forgot to use .equals(), as the sessionId you have mentioned is of String type.

msrd0
  • 7,816
  • 9
  • 47
  • 82
Ashis Jena
  • 450
  • 1
  • 8
  • 17
  • 1
    must add explaination with your code...giving just code is not good approach of giving ans – kirti Oct 13 '14 at 16:05