WHISKAS
WHISKAS

Reputation: 3

How do I average the contents in ArrayList?

This TestCode is supposed to create an stream of numbers in seconds. Collect 10 samples, and average the time which each samples comes out. I did try to use if-else, but the variable from if doesn't share with else. Please correct me if I'm wrong. I don't understand lambda just yet.

public class TestCode {

    private int eachTwoSec;

    // supposed to aList.add 10 items
    // average the time needed in between each aList.add (2 obviously)
    public void avgTimeTaken() {
        ArrayList aList = new ArrayList();
        for (int i = 0; i < 10; i++) {
            aList.add(eachTwoSec);
        }
    }

    // return a number every two seconds (endless stream of samples)
    // samples 50,52,54,56,58,60,2,4,6,8,10
    public void twoSecTime() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(Dummies.class.getName()).log(Level.SEVERE, null, ex);
        }

        LocalDateTime ldt = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ss");
        eachTwoSec = Integer.parseInt(ldt.format(dtf));
        System.out.println(eachTwoSec);
        twoSecTime();
    }

    public TestCode() {
        // construct
        avgTimeTaken();
        new Thread(this::twoSecTime).start();
    }

    public static void main(String[] args) {
        // just a start point
        new TestCode();
    }
}

Upvotes: 0

Views: 91

Answers (2)

sprinter
sprinter

Reputation: 27996

The literal answer to the question "How do I average the contents in ArrayList?" for a List<Integer> is:

list.stream().mapToInt(Integer::intValue).average();

Though I suspect that's not really what you need to know given the concurrency issues in your code.

Upvotes: 1

WJS
WJS

Reputation: 40057

This may help to do what you want (or give you a place from which to proceed).

  • I use a timer to take action every 2000 ms. I prefer using the Swing timer and not messing around with TimerTasks.
  • I don't just add 2 sec but grab the current nanoSecond time
  • This introduces latency errors introduced by various parts of the code and of synchronicities.
  • I add the microseconds to the ArrayList. These are in the form of delta from the most recent to the previously recorded value.
  • and when count == 10 I stop the timer and invoke the averaging method.
  • Most of the work is done on the EDT (normally a bad thing but okay for this exercise). If that were a problem, another thread could be started to handle the load.
  • I then use the original main thread to signal wait to leave the JVM. Imo, preferred over System.exit(0);

The gathered data and final average are all in microseconds.

import java.util.ArrayList;
import javax.swing.Timer;

public class TestCode {
    
    Timer timer;
    int delay = 2000; // milliseconds
    int count = 0;
    long last;
    
    ArrayList<Integer> aList = new ArrayList<>();
    Object mainThread;
    
    public void avgTimeTaken() {
        
        double sum = 0;
        for (Integer secs : aList) {
            sum += secs;
        }
        System.out.println("Avg = " + sum / aList.size());
    }
    
    public void twoSecTime() {
        long now = System.nanoTime();
        int delta = (int) (now / 1000 - last / 1000); // microseconds
        last = now;
        aList.add(delta);
        System.out.println(delta);
        count++;
        if (count == 10) {
            // stop the time
            timer.stop();
            // get the averages
            avgTimeTaken();
            // wake up the wait to exit the JVM
            // twoSecTime is run on the EDT via timer
            // so need to use mainThread
            synchronized (mainThread) {
                mainThread.notifyAll(); 
            }
        }
    }
    
    public static void main(String[] args) {
        new TestCode().start();
    }
    
    public void start() {
        mainThread = this;
        timer = new Timer(2000, (ae) -> twoSecTime());
        last = System.nanoTime(); // initialize last
        timer.start();
        synchronized (this) {
            try {
                wait(); // main thread waiting until all is done
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
    }
}

Upvotes: 0

Related Questions