Multi arraylist, trying to store timestamp with data - java

We have the code below which is a simple loop iterating through an arraylist and storing each iterated value into another arraylist. Each time an iteration is achieved, a timestamp value is obtained. How do we create or change the existing arrylist to store both a value and a timestamp together. Can we create a multi dimentional arraylist to do this ie arraylist [0],[0]. if so how?
int counter = 0; //current number of iterations
ArrayList<String> logData = new ArrayList<String>();
while (counter < TemData.size()) {
Thread.sleep(5000); // Sleep for 5000 milliseconds (5 seconds)
nowTime = new GetCurrentTimeStamp();
logData.add((String) TemData.get(counter));
System.out.println();
System.out.println("Outputting Array Data >> " + logData.get(counter));
//add to timestamp ArrayList
nowTime = new GetCurrentTimeStamp();
counter++; //increment counter)
}
This is GetCurrentTimeStamp class
public class GetCurrentTimeStamp {
public GetCurrentTimeStamp()
public GetCurrentTimeStamp() {
//Date object
Date date= new Date();
//getTime() returns current time in milliseconds
long time = date.getTime();
//Passed the milliseconds to constructor of Timestamp class
Timestamp ts = new Timestamp(time);
System.out.println("Time Stamp >> "+ts);
}
}

Why don't you create a simple class to store your values?
class MyData {
private String myString;
private Timestamp myTime;
MyData(String string, Timestamp timestamp) {
this.myString = string;
this.myTime = timestamp;
}
// getters and setters of your choosing
}
Then in your code, instead of
ArrayList<String> logData = new ArrayList<String>(); do a ArrayList<MyData> logData = new ArrayList<MyData>(); instead.
In your loop you could do something like
MyData myData = new MyData((String) TemData.get(counter), nowtime);
logData.add(myData);
... or tweak the actual add to the ArrayList based on which value of nowTime you wanted to use.

Multidimensional Arrays are possible, as are multidimensional ArrayLists, but I don't think that's what you need.
Just to reiterate what you're trying to do: You're trying to store a String and a Timestamp together. The simplest way of doing this with arrays is somewhat crude. You make two arrays: One for the Strings and one for the Timestamps, and you 'associate' values via their index. Eg:
ArrayList<String> strings = new ArrayList<String>();
ArrayList<Timestamp> times= new ArrayList<Timestamp>();
...
strings.get(5); // Your sixth logged entry
times.get(5); // and its associate timestamp
Like I said this is crude, and prone to errors because you need to ensure the indices match up at all times.
Another possibility is to use an associative collection of some sort. Hash maps come to mind. For example:
HashMap<Timestamp, String> logEntries = new HashMap<Timestamp, String>();
logEntries.put(GetCurrentTimeStamp(), (String) TemData.get(counter));
When searching/iterating through the collection, you would iterate through all of the keys in logEntries.keySet(). Eg:
for (Timestamp key : logEntries.keySet())
{
String value = logEntries.get(key);
// Do your processing here - you now know the key and value pair.
}

Related

Iterate over a HashMap with multiple values per key

I am currently learning sets and maps through university (still using Java 7).
They have given us a half finished to-do list app to complete. Currently the to-do list takes three String local variables to allow the user to state a job (aJob), a time to do it (aTime) and a date to do it (aDate).
The app also has an instance variable (today) that holds todays date.
I need to come up with a way to check the HashMap for any tasks that are due today. So I need to be able to query just the HashMap values attributed by the aDate local variable.
I know that to iterate Maps that I can place the keys or the values into a Set and then iterate over the set - not a problem. But if I use the values() method (within the Map class) to put these into a set - it places all three Strings per key into the set. I just want to move the aDate values into a set.
Any ideas?
I only seem to be able to find examples where the Maps have just a single Key and Single Value. This list has a single key and three values per key.
Any pointers would be good?
Kind Regards
Edit.....
Just thought I would add some code to help as there have been several different approaches - which I am all very greatful for. But not sure if they suit my needs....
The Job Class is constructed as such...
public Job(String aJob, String aDate, String aTime)
{
Job = aJob;
date = aDate;
time = aTime;
}
I then create the map within the instance declarations for the To Do List class....
Map<Integer, Job> toDoList = new HashMap<>();
So I need to know the best way to iterate over this map, but it is only the Job attribute 'aDate' that is possibly going to hold the value I am after.
Not sure if that helps at all?
Kind Regards
If really the only structure you're allowed to use is a Map where each key has 3 values (which is the case if I understand correctly), of which only one is a Date, you technically could do the following:
map.values()
.stream()
.filter(Date.class::isInstance)
...whatever else you want to do
The other suggested solutions are far better though, design wise.
If you can't use a custom class, as suggested by Toisen, maybe HashMap<String, HashMap<String, ArrayList<String>>> could do the trick for you.
I've added a sample of how to use it (as well as populating it with some random data)
public class FunkyMap {
private HashMap<String, HashMap<String, ArrayList<String>>> jobs;
// For random data
private String[] job = {"EAT", "SLEEP", "FART", "RELAX", "WORK"};
private String[] time = {"MORNING", "BEFORENOON", "NOON", "AFTERNOON", "EVENING", "MIDNIGHT"};
private String[] date = {"FIRST", "SECOND", "THIRD", "FOURTH"};
public FunkyMap() {
jobs = new HashMap<>();
// To populate some random data
Random r = new Random();
for(int i = 0; i < 20; i++) {
String d = date[r.nextInt(date.length)];
if(jobs.containsKey(d)) {
HashMap<String, ArrayList<String>> inner = jobs.get(d);
String t = time[r.nextInt(time.length)];
if(inner.containsKey(t)) {
inner.get(t).add(job[r.nextInt(job.length)]);
} else {
List<String> s = Arrays.asList(new String(job[r.nextInt(job.length)]));
inner.put(t, new ArrayList<String>(s));
}
} else {
jobs.put(d, new HashMap<String, ArrayList<String>>());
}
}
// Actual iteration over date => time => jobs
Iterator<String> i = jobs.keySet().iterator();
while(i.hasNext()) {
String iKey = i.next();
HashMap<String, ArrayList<String>> inner = jobs.get(iKey);
System.out.println("Jobs scheduled for " + iKey);
Iterator<String> j = inner.keySet().iterator();
while(j.hasNext()) {
String jKey = j.next();
ArrayList<String> actualJobs = inner.get(jKey);
System.out.println("\tAt " + jKey);
for(String s : actualJobs) {
System.out.println("\t\tDo " + s);
}
}
}
}
public static void main(String[] args) {
new FunkyMap();
}
}
I took the liberty to assume that dates were unique, and time was unique per date, while a time could hold any number of jobs including duplicates. If the last assumption with jobs is not true, you could swap ArrayList<String> with Set<String>.
Just create a class that holds all data that you need. E.g.
If you need something strange like Map<String, Tuple<String, Integer, Date>> just make a new class that holds the Tuple:
class TupleHolder {
private String firstValue;
private Integer secondValue;
private Date thirdValue;
// get/set here...
}
and use it: Map<String, TupleHolder>

compare and update two arraylist java android

I have an two array lists with multiple values at single index. I am adding the values like below:
ArrayList<String> list1 = new ArrayList<String>();
list1.addAll(Arrays.asList("iFRa1wVJ","Breakfast","7:00am","8:30am"));
list1.addAll(Arrays.asList("JyvmCZhw","Lunch","1:00pm","3:00pm"));
list1.addAll(Arrays.asList("HR6ovPjE","Dinner","7:30pm","9:30pm"));
ArrayList<String> list2 = new ArrayList<String>();
list2.addAll(Arrays.asList("iFRa1wVJ","Breakfast1","9:00am","10:30am"));
list2.addAll(Arrays.asList("JyvmCZhw","Lunch","2:00pm","3:00pm"));
list2.addAll(Arrays.asList("HR6ovPjE","Dinner","8:30pm","9:30pm"));
Expected result is as below:
iFRa1wVJ,Breakfast,7:00am,8:30am --> Breakfast1 is overwriiten as Breakfast from list1
JyvmCZhw,Lunch,1:00pm,3:00pm --> 2:00pm is overwriiten as 1:00pm from list1
HR6ovPjE,Dinner,7:30pm,9:30pm --> 8:30pm is overwriiten as 7:30pm from list1
I need to compare the values of each index and update the second list with the values of first list. How to do the comparisons of the list in each index. Any help will appreciated. Thanks.
It sounds as though you'd be better off using a Map or Set instead of a List. For example:
class Meal {
//You may want to store times in a different format, i.e. a long in millisecond
private final String name, startTime, endTime;
Meal(String name, String startTime, String endTime) {
this.name = name;
this.startTime = startTime;
this.endTime = endTime;
}
//getName(), getStartTime(), getEndTime()...
}
And in your map...
final Map<String, Meal> map = new HashMap<>();
map.put("iFRa1wVJ", new Meal("Breakfast","7:00am","8:30am"));
map.put("iFRa1wVJ", new Meal("Breakfast","9:00am","10:30am"));
The second "Breakfast" will replace the first as they share the same key.
You wanted two array lists with multiple values at each index, but in your original code ArrayList<String> is just an array with a single String object at each index. So I changed the data structure to hold a list of Strings. If all you really want to do is update each index with the value at the corresponding index of list1 you can just update everything at the index.
ArrayList<List<String>> list1 = new ArrayList<List<String>>();
list1.add(Arrays.asList("iFRa1wVJ", "Breakfast", "7:00am", "8:30am"));
list1.add(Arrays.asList("JyvmCZhw", "Lunch", "1:00pm", "3:00pm"));
list1.add(Arrays.asList("HR6ovPjE", "Dinner", "7:30pm", "9:30pm"));
ArrayList<List<String>> list2 = new ArrayList<List<String>>();
list2.add(Arrays.asList("iFRa1wVJ", "Breakfast1", "9:00am", "10:30am"));
list2.add(Arrays.asList("JyvmCZhw", "Lunch", "2:00pm", "4:00pm"));
list2.add(Arrays.asList("HR6ovPjE", "Dinner", "8:30pm", "9:30pm"));
for (int i = 0; i < list1.size(); i++) {
list2.set(i, list1.get(i));
}
System.out.println(list1);

Why am I unable to assign an embedded ArrayList<Integer> to a locally declared ArrayList<Integer>?

Sorry if the title is not clear, I'm not very good with programming jargon.
I have 2 string ArrayLists and an integer ArrayList obtained from one method which is passed to a separate method through the collection LinkedHashMap< String, List< String>>. However, when I try to set the integer ArrayList into a empty ArrayList declared in the receiving method, it shows the syntax error: "incompatible types: List< String> cannot be converted to List< Integer>".
Starter Method:
public static void main(String[] args) {
try{
LinkedHashMap lhm = new LinkedHashMap();
List<String> listEPC = new ArrayList<String>();
List<String> listTimeStamp = new ArrayList<String>();
List<Integer> listAntenna = new ArrayList<Integer>();
String tagID = "EQ5237";
String TimeStampStr = "12:23:22";
int tagAntenna = 2;
listEPC.add(tagID);
listTimeStamp.add(TimeStampStr);
listAntenna.add(tagAntenna);
lhm.put("epcs", listEPC);
lhm.put("timestamps", listTimeStamp);
lhm.put("antennas", listAntenna);
insertData insert = new insertData();
insert.insertData(lhm); //send map with values to new method
}catch(Exception e){
e.printStackTrace();
}
}
Receiving Method:
public class insertData {
public void insertData(LinkedHashMap<String, List<String>> readMap) {
List<String> listEPC = new ArrayList<String>();
List<String> listTimeStamp = new ArrayList<String>();
List<Integer> listAntenna = new ArrayList<Integer>();
String EPC = null;
String TimeStamp = null;
Integer Antenna = null;
listEPC = readMap.get("epcs");
listTimeStamp = readMap.get("timestamps");
listAntenna = readMap.get("antennas"); //error message here
for(int i=0; i<readMap.size(); i++){
EPC = listEPC.get(i);
TimeStamp = listTimeStamp.get(i);
Antenna = listAntenna.get(i);
System.out.println("Entry " + i );
System.out.println("Values: " + EPC + TimeStamp + Antenna);
}
}
}
This code works only if I change all instances of integers to strings, which is not what I would like in my actual code. Why is it so and how do I work around it?
You can't assign a List<String> to a List<Integer>. The elements are fundamentally different types.
You would need to construct a new List:
List<Integer> listOfIntegers = new ArrayList<>();
for (String entry : listOfStrings) {
listOfIntegers.add(Integer.valueOf(entry);
}
Of course, you also need to handle the possibility that elements of the list cannot be parsed as integers.
However, you are just throwing away type information by stuffing everything into a single map. It would be better to pass the three lists separately:
insertData(listEPC, listTimestamp, listAntenna);
and then you can have different list types in the method signature:
void insertData(
List<String> listEPC,
List<String> listTimestamp,
List<Integer> listAntenna) { ... }
I am going to include the proper answer at the bottom, but in regards to your question title, you'll have to change your method signature to:
LinkedHashmap<String, List<?>> readMap;
Then either cast the lists, which will cause an unsafe cast. eg.
List<String> listEPC = (List<String>)readMap.get("epcs");
Or cast the object.
List<?> listEPC = readMap.get("epcs");
Then in the loop cast.
EPC = (String)listEPC.get(i);
Note, these are not good solutions.
What you should have is one List that contains an object with all of the data's you need.
I can imagine the thought process went something along these lines, "I have these things, and they contain two strings and an integer. I will create a variable for each." Then you ask the question, "How do I create a collection of these things?"
The wrong answer to this question is, "I will make a list for each value, and match associated values by index." The correct answer is, "I will create a class to represent my data, and store that in a list." This is the basic essence of object orient programming (welcome to java).
First we design the class:
class EPCThing{
String EPC;
String timeStamp;
int Antennas;
public EPCThing(String tagId, String timeStamp, int antennas){
EPC=tagId;
this.timeStamp = timeStamp;
Antennas = antennas;
}
#Override
public String toString(){
return "Values: " + EPC + TimeStamp + Antenna
}
}
Now your program's main method will be something like.
List<EPCThing> things = new ArrayList<>();
String tagID = "EQ5237";
String TimeStampStr = "12:23:22";
int tagAntenna = 2;
EPCThing thing = new EPCThing(tagID, TimeStampStr, tagAntenna);
things.add(thing);
insertData insert = new insertData();
insert.insertData(things);
Then we can fix your insertData method
public void insertData(List<EPCThing> things) {
for(int i=0; i<things.size(); i++){
System.out.println("Entry " + i );
System.out.println("Values: " + things.get(i));
}
}

String[] or ArrayList better as Key in HashMap?

So I need to choose between
HashMap<String[], Object>
HashMap<ArrayList<String>,Object>
My input Parameter is: ArrayList<String> in.
The whole ArrayList<String> in cannot be the key, since it does contain elements, which are not supposed to be like a Primary Key in a database. I do know, that the first n elements of the incoming ArrayList<String> in supposed to be the primary Keys.
Which one would be faster?
Scenario:
HashMap<ArrayList<String>, Object> hmAL = new HashMap<>();
HashMap<String[], Object> hmSA = new HashMap<>();
ArrayList<String> in = new ArrayList<>();
fillWithStuff(in);
//Which one would be faster?
getObject(in,hmAL,5);
getObject(in,hmSA,5);
With Option 1:
private Object getObject(ArrayList<String> in, HashMap<ArrayList<String>, Object> hm, int n){
return hm.get(in.sublist(0,n));
}
With Option 2:
private Object getObject(ArrayList<String> in, HashMap<String[], Object> hm, int n){
String[] temp = new String[n];
for(int i=0; i<n; i++)
temp[i]=in.get(i);
return hm.get(temp);
}
Considering:
Which is faster? Short the list, or copy to an array?
I'm wondering, which hash (since it is a HashMap) would be faster. Hashing of a ArrayList, or an equal-sized array. Or doesn't it make any difference?
Using String[] is not a good idea because it does not implement hashCode(). This means if you have 2 string arrays which are different objects but with the exact same values, the map will not find it.
The implementation of 'hashCode` seems to use each of the string elements hashcode so the lookup in a map would succeed. So I'd go with this one.
That said, I would rather build a key myself based on the objects in the list.
Dealing with copying only
The subList method is implemented very efficiently in Java 7+, not requiring any copying at all. It simply returns a view directly onto the original array. Thus, in Java 7+, it will be faster than the copy element by element method. However, in Java 6, both ways are essentially equivalent.
Dealing with the method as a whole
If you look at the whole method, your choice is no longer a choice. If you want the method to function, you will have to use the first implementation. Array hashCode() does not look at the elements inside it---only the identity of the array. Because you are creating the array in your method, the Map.get() will necessary return null.
On the other hand, the List.hashCode() method runs a hash on all of the contained elements, meaning that it will successfully match if all of the contained elements are the same.
Your choice is clear.
Just to add on above two answers, I have tested in Java 7 and found on an average with list it's 50 times faster with 2000000 total elements and 1000000 elements which participate in calculating hashcode i.e. primary keys (hypothetical number). Below is the program.
public class TestHashing {
public static void main(String[] args) {
HashMap<ArrayList<String>, Object> hmAL = new HashMap();
HashMap<String[], Object> hmSA = new HashMap<>();
ArrayList<String> in = new ArrayList<>();
fillWithStuff(in);
// Which one would be faster?
long start = System.nanoTime();
getObject(in, hmAL, 1000000);
long end = System.nanoTime();
long firstTime = (end-start);
System.out.println("firstTime :: "+ firstTime);
start = System.nanoTime();
getObject1(in, hmSA, 1000000);
end = System.nanoTime();
long secondTime = (end-start);
System.out.println("secondTime :: "+ secondTime);
System.out.println("First is faster by "+ secondTime/firstTime);
}
private static void fillWithStuff(ArrayList<String> in) {
for(int i =0; i< 2000000; i++) {
in.add(i+"");
}
}
private static Object getObject(ArrayList<String> in,
HashMap<ArrayList<String>, Object> hm, int n) {
return hm.get(in.subList(0, n));
}
private static Object getObject1(ArrayList<String> in, HashMap<String[], Object> hm, int n){
String[] temp = new String[n];
for(int i=0; i<n; i++)
temp[i]=in.get(i);
return hm.get(temp);
}
}
Output
firstTime :: 218000
secondTime :: 11627000
First is faster by 53

How to remove duplicates from list<object>

I have a object in java called foo.
I can do foo.getDate(); and that will give me the date of one item.
But now I have a list<foo> and I want to get per item one date.
So if I loop through my list I will see this output:
3-1-2015
3-1-2015
5-1-2015
8-1-2015
8-1-2015
But I want to see:
3-1-2015
5-1-2015
8-1-2015
So I want that only the first item with a unique date will be added to the list.
How can I do this in Java?
Thanks in advance!
Probably the most easy way would be use a map (HashMap for example)... Use the Date as a key, then put all your Foo objects into it. Then every time a key already exists the value will be overwritten and you'll end up with only one Foo object per Date. If you need a list (for sorting, for example) you can do something like new ArrayList<Foo>( myMap.values() ); then.
Create Set which will store unique Dates. If date from your foo instance was not already added to set add this instance to list containing foo objects with unique dates.
List<Foo> list = new ArrayList<>();
//fill list with your foo instances
Set<Date> uniqueDates = new HashSet<>();
List<Foo> resultList = new ArrayList<>();
for (Foo f : list){
if (uniqueDates.add(f.getDate())){//if I was able to add date to set
//it means that instance with this date is seen first time
//so I can add it to result list
resultList.add(f);
}
}
well you probably should use Set for this.
Just to add to #Pshemo's answer, doing the same with Java 8 is straightforward:
public class RemoveDuplicates {
public static void main(String[] args) {
// Initialize some dates
long now = System.currentTimeMillis();
Date d1 = new Date(now);
Date d2 = new Date(now - 10_000_000_000L);
Date d3 = new Date(now - 100_000_000_000L);
// Initialize some Foos with the dates
List<Foo> list = new ArrayList<>(Arrays.asList(
new Foo(d3), new Foo(d3), new Foo(d2),
new Foo(d1), new Foo(d1)));
Set<Date> uniqueDates = new HashSet<>();
// Filter foos whose date is already in the set
List<Foo> distinct = list.stream().filter(
f -> uniqueDates.add(f.getDate())).
collect(Collectors.toList());
System.out.println(distinct); // [Foo [date=17/01/12],
// Foo [date=24/11/14],
// Foo [date=19/03/15]]
}
static class Foo {
private static DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT);
private final Date date;
Date getDate() {
return this.date;
}
Foo(Date date) {
this.date = date;
}
#Override
public String toString() {
return "Foo [date=" + formatter.format(this.date) + "]";
}
}
}
The principle is exactly the same: if the date is already in the set, then the Foo is filtered from the stream.

Categories