Is this correct?
ArrayList<Timestamp> timeStampList = new ArrayList<Timestamp>();
timeStampList.add(0, new Timestamp(System.currentTimeMillis()));
Thread.sleep(600);
timeStampList.add(1, new Timestamp(System.currentTimeMillis()));
Collections.sort(timeStampList);
Timestamp tempStamp = timeStampList.get(0);
for (Timestamp startstamp : timeStampList)
{
if (tempStamp != startstamp)
{
long diffTime = startstamp.getTime() - tempStamp.getTime();
diffDays = diffTime / (1000 * 60 * 60);
if(diffDays > 24)
{
System.out.println(diffDays / 24 +"Day" + " "+diffDays % 24 + "hours");
}
tempStamp = startstamp;
}
}
I am NOT sure how I can find the oldest timestamp in the array list. Any advice or direct answer is appreciated. Thanks a lot. This current code I think only compares.
EDIT: So assume I do not use Collection.sort in this context, I know I did apply that when I posted, but lets assume I want to know how to compare and find the oldest timestamp of all in the arrayList via a for-loop.
If, based on your post, you didn't want to sort your data, but instead wanted to just iterate through your entire collection of Timestamp objects and compare that way, you could use the Timestamp's after() method, which establishes whether a Timestamp occurs after the Timestamp provided as the argument of the function.
public Timestamp getOldestTimeStamp(ArrayList<Timestamp> timeStampList)
{
if (timeStampList != null || timeStampList.length() == 0)
{
return null;
}
Timestamp oldestTimestamp = timeStampList.get(0);
for (int i = 1; i < timeStampList.length(); i++)
{
if (oldestTimeStamp.after(timeStampList.get(i))
{
oldestTimeStamp = timeStampList.get(i);
}
}
// oldestTimeStamp is now the oldest Timestamp in the ArrayList
return oldestTimeStamp;
}
I could've sworn I included this in my first edit, but it looks like it didn't take. Everyone in the comments is correct in their wish for you to use the built-in features of the language instead of rolling your own. In this case, you would be far better suited learning to use simple language features like Collections.sort() and Collections.min(), which will invariably be as efficient and typically more so than the kind of code you or I will write, and significantly more succinct than a 12-line method like the one above.
Related
Right now I write the function to get the number of working days myself. Instead of course it is much better to make use of Spring data and let the database make the calculation.
So how could I write the second function in Spring data.
It should be something like. Count by Date Distinct group by date from WorkingDay . A workingDayObject can occur more than once per day if somebody worked on different projects . That's way I use a hashset in my function to get just the days.
private double calculateOvertimeHours(WorkingMonth month)
{
double workedHours = Util.convertTimeToDoubleDecimal(month.getWorkedHours());
//Here I use a Spring data method as you can see
List<WorkingDay> lstWorkingDays = workingDayDao.findByWorkingMonthOrderByDateAsc(month);
return workedHours - calcNumberWorkDays(lstWorkingDays) * 8;
}
private int calcNumberWorkDays(List<WorkingDay> lstWorkingDays)
{
Set<Integer> hashSetDays = new HashSet<Integer>();
Calendar cal = Calendar.getInstance();
for(WorkingDay workingDay : lstWorkingDays)
{
cal.setTime(workingDay.getDate());
hashSetDays.add(cal.get(Calendar.DAY_OF_MONTH));
}
return hashSetDays.size();
}
I have 3 variables with long values timestamp1 timestamp2 timestamp3 and an arraylist timestampList. I want to compare them in an if/else. It could be possible, that the three timestamps have different values, so I want to add the values with the min value to the list. I should also mention, that these timestamps are coming in every 2 minutes.
When the three variables are same, I could simply do
if(timestamp1 == timestamp2 && timestamp2 == timestamp3){
timestampList.add(timestamp 1); //since they are the same it doesn't matter which i add to the list
.
.
.
}
now in the else or else if I want to check the three timestamps and get the variable with the min value, not the value itself. Because I need the variable for other variables further in the code. Of course I also want to add the min value to the list too. I can imagine, that I could do more if/else branches in the else like
else{
if(timestamp1 < timestamp2){
if(timestamp1 < timestamp3){
...
}else{
...
}
}
}
but that would be too much and there is certainly a better way.
Try this:
long timestamp1 = 1;
long timestamp2 = 2;
long timestamp3 = 3;
long result = LongStream.of(timestamp1, timestamp2, timestamp3)
.min()
.getAsLong();
You can not really get a "pointer" to a variable in Java, as you could in C. The closest thing would be using a mutable type instead, so instead of assigning a new value to the variable you can modify an attribute of the existing instance, and the change will be reflected anywhere else in your code where you have a reference to that instance.
For example, you could wrap your long timestamps into AtomicLong instances:
// wrap in mutable AtomicLong instances
AtomicLong timestamp1 = new AtomicLong(123);
AtomicLong timestamp2 = new AtomicLong(456);
AtomicLong timestamp3 = new AtomicLong(789);
// get minimum or maximum, using streams or any other way
AtomicLong minTimeStamp = Stream.of(timestamp1, timestamp2, timestamp3)
.min(Comparator.comparing(AtomicLong::get)).get();
// modify value
System.out.println(minTimeStamp); // 123
timestamp1.set(1000); // change original variable
System.out.println(minTimeStamp); // 1000
Another way to keep a variable to a certain value would be to use Optional<Long> as #tobias_k mentioned in his comment. An alternative to Stream would be to use a TreeSet. When creating the TreeSet we provide the Function to compare the elements. After all timestamps has been added, we can call TreeSet.first() to get the minimum element.
List<Optional<Long>> timestamps = Arrays.asList(Optional.of(1234l), Optional.of(2345l), Optional.of(1234l));
TreeSet<Optional<Long>> setOfTimestamps = new TreeSet<>(Comparator.comparing(Optional::get));
setOfTimestamps.addAll(timestamps);
Optional<Long> min = setOfTimestamps.first();
System.out.println(min.get());
So I went with the idea of #Amadan and created an array with the timestamps. But after thinking a little bit, I came to the conclusion that it would be possible without getting the variable.
long[] arrayDo = new long[3];
arrayDo[0] = eafedo5.getServiceInformation(eafedo5Count).getTimestamp();
arrayDo[1] = eafedo6.getServiceInformation(eafedo6Count).getTimestamp();
arrayDo[2] = eafedo7.getServiceInformation(eafedo7Count).getTimestamp();
Then I calculate the minValue of the array.
long minTimestamp = Math.min(arrayDo[0],Math.min(arrayDo[1],arrayDo[2]));
Then I ask if the timestamps are equal to minValue
if(!timestamps.contains(minTimestamp)){
timestamps.add(minTimestamp);
}
if(eafedo5.getServiceInformation(eafedo5Count).getTimestamp() ==minTimestamp){
for(CHostNeighbor n : hostNeighborsEafedo5){
msgsCountDo += n.getInboundMsgs();
}
eafedo5Count--;
}
if(eafedo6.getServiceInformation(eafedo6Count).getTimestamp() ==minTimestamp){
for(CHostNeighbor n : hostNeighborsEafedo6){
msgsCountDo += n.getInboundMsgs();
}
eafedo6Count--;
}
if(eafedo7.getServiceInformation(eafedo7Count).getTimestamp() ==minTimestamp){
for(CHostNeighbor n : hostNeighborsEafedo7){
msgsCountDo += n.getInboundMsgs();
}
eafedo7Count--;
}
msgsDo.add(msgsCountDo);
I mentioned in my question that I need the variable for later purposes. It was because I needed the name of the variable to decrement the count variable of the specific host. (the eafed... are hosts).
Thanks for all the answers!
Does the Arraylist object store the last requested value in memory to access it faster the next time? Or do I need to do this myself?
Or more concretely, in terms of performance, is it better to do this :
for (int i = 0; i < myArray.size(); i++){
int value = myArray.get(i);
int result = value + 2 * value - 5 / value;
}
Instead of doing this :
for (int i = 0; i < myArray.size(); i++)
int result = myArray.get(i) + 2 * myArray.get(i) - 5 / myArray.get(i);
In terms of performance, it doesn't matter one bit. No, ArrayList doesn't cache anything, although the JITted end result could be a different issue.
If you're wondering which version to use, use the first one. It's clearer.
You can answer your (first) question yourself by looking into the actual source:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
So: No, there is no caching taking place but you can also see that there is no much of an impact in terms of performance because the get method is essentially just an access to an array.
But it's still good to avoid multiple calls for some reasons:
int result = value + 2 * value - 5 / value is easier to understand (i.e. realizing that you use the same value three times in your calculation)
If you later decide to change the underlying list (e.g. to a LinkedList) you might end up with an impact on performance and then have to change your code to get around it.
As long as you don't synchronize the access to the list, repeated calls of get(index) might actually return different values if between two calls a call of set(index, value) has taken place (even in small souce blocks like this, it's possible to happen - BTST)
The second point has also a consequence in terms of how to access all values of a list, that leads to the decision to avoid list.get(i) altogether if you're going to iterate over all elements in a list. In that case it's better to use the Iterator or streams:
You code would then look like this:
Iterator it = myArray.iterator();
while (it.hasNext()) {
int value = it.next();
int result = value + 2 * value - 5 / value;
}
LinkedList is very slow when trying to access elements in it by specific index but can iteratre quite fast from one element to the next, so the Iterator returned by LinkedList makes use of that while the Iterator returned by ArrayList simply accesses the internal array (without the need to do the repeated range check calls you can see in the get-method above
It's difficult for me to think how to ask this so I will create an example to demonstrate what I am asking for:
Suppose I have my model:
public class UserEvaluation {
String name;
Date respondedAt;
}
public class Evaluation {
String name;
List<UserEvaluation> userEvaluations;
{
And then in my EvaluationService I need to know the amount of userEvaluations which have been responded (respondedAt != null).
Possible solutions:
1 By iterating through all the items:
Evaluation evaluation = evaluationRepository.get(1);
Long count = 0;
for(UserEvaluation userEvaluation : evaluation.getUserEvaluations()) {
if(userEvaluation.getRespondedAt() != null) {
count++;
}
}
2 By Lambda Expressions:
Evaluation evaluation = evaluationRepository.get(1);
Long count = evaluation.getUserEvaluations().stream()
.filter(ue -> ue.getRespondedAt() != null)
.count();
3 By querying de database:
Evaluation evaluation = evaluationRepository.get(1);
Long count = userEvaluationRepository.getRespondedCountByEvaluation(evaluation); //And implement this simple count query.
So this is the simpliest thing. Which I would pick? I'm using a lot of iterators and lambda stream iterator expressions in my app. But I am worried about that should be an error and I would need to interact more with the database? Should I? Should I not?
If you are not sure I would design it so you can change it as required. Have a DAO implementation which accesses the database, but one which could be changed to use in memory data if you determine using the database is not fast enough.
interface DatabaseDAO {
long getRespondedCountByEvaluation(Evaluation e);
}
It depends on which approach would retrieve less data. If you grab the data once and extract information from that many times it can be faster, but if you are only getting a small portion each time and have an indexed database it can be much faster. I would design it
I'm using Collections.sort to sort a ArrayList of objects, and I want to see if there is a more efficient compareTo method for what I'm trying to do.
Here's the method:
#Override
public int compareTo(Song s) {
if (runningTime > s.runningTime) {
return -1;
} else if (runningTime < s.runningTime) {
return 1;
}
int lastCmp = title.compareTo(s.title);
return (lastCmp != 0 ? lastCmp : composer.compareTo(s.composer));
}
If anyone could suggest a more efficient method (i.e. quicker runtime) I would be very grateful.
Just like MeBigFatGuy said, any improvement is insignificant, but I think you can still clean up the code a bit to reduce unnecessary if-else condition. My two cents.
public int compareTo(Song s) {
if (runningTime != s.runningTime) {
return s.runningTime - runningTime;
}
else {
int lastCmp = title.compareTo(s.title);
return (lastCmp != 0 ? lastCmp : composer.compareTo(s.composer));
}
}
Assuming that the priority of song ordering is fixed (running time; title if running times are the same; composer if running times and titles are the same), then there's not much you can do better. If the priorities are not fixed, then perhaps testing on composer before title may speed things up a bit; it depends on your actual data. I'd keep the test on running times first, because that is always going to be faster than string comparisons.
Looks fine to me as well. If you're running into performance problems, you might check if you're sorting too often. Not sure if Collections.sort is sensitive to this by now, but you might gain sth if you don't resort an already sorted list after inserting only a few songs
Depending on how long it takes to read a property value, it might be a tiny bit quicker to store runningTime and s.runningTime into local variables first. So on average, instead of reading them 1.5 or more times per call, you'd only read them once per call.