I have n number of users with their name and time value eg
String userName = "user1"
String time = "09:30"
In an ArrayList ArrayList<Map<String,String>> userData = new ArrayList<>( );
I would like to have something like this
But i'm confused with the K,V values. Should i first convert the userName and time in Map values separately? like
Map<String, String> uName = new HashMap<String, String>();
Map<String, String> uTime = new HashMap<String, String>();
uName.put("userName",userName);
uTime.put("time",time);
But then, how to add the two values in the same index of the Array?
Or how which steps should i do first?
Could you please, write down an example or references that could help me as well.
Thank you!
If I understand your question right, you may want to create a class:
public class MyClass {
private String userName;
private LocalTime time;
public MyClass(String userName, LocalTime time) {
this.userName = userName;
this.time = time;
}
public String getUserName() { return userName; }
public LocalTime getUserName() { return time; }
}
The you can simply have an ArrayList<MyClass>
. You may want the time variable to be of type String
, whatever works best for you. I would not recommend storing timestamps as strings though.
I don't think you need a ArrayList of Maps here, there are two more suitable alternatives in my mind:
User
that will have two string variables - name and time, and have an ArrayList of User either will do, having ArrayList of Maps seems redundant
Just use one map only for each index. For instance:
List<Map<String, String>> userData = new ArrayList<Map<String, String>>();
Map<String, String> user1 = new HashMap<String, String>();
user1.put("name", "John");
user1.put("time", "9:03");
userData.add(user1);
While this works, then if you need to look for any user you'll have to go through the list and find the user you're looking for by accessing the map. So you could have a Map of Maps: Map<String, Map<String, String>>
this way:
Map<String, Map<String, String>> userData = new HashMap<String, Map<String, String>>();
Map<String, String> user1 = new HashMap<String, String>();
user1.put("time", "9:03");
userData.put("John", user1);
this way if you're looking for John's data you can just simply do userData.get("John")
An even better solution would be to have a User class with defined properties. For instance:
public class User {
private String name;
private String time;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
}
Map<String, User> userData = new HashMap<String, User>();
User user1 = new User();
user1.setName("John");
user1.setTime("9:03");
userData.put(user1.getName(), user1);
Based on your question "Is it possible to keep the map sorted everytime a user is inserted?" the answer is NO. Maps are unsorted. You seem to need a SortedList that inserts items ordered. Here's a simple Implementation:
public class SortedList<T> implements List<T> {
private List<T> delegate;
private Comparator<T> order;
public SortedList(List<T> delegate, Comparator<T> order) {
this.delegate = delegate;
this.order = order;
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean contains(Object o) {
return delegate.contains(o);
}
@Override
public Iterator<T> iterator() {
return delegate.iterator();
}
@Override
public Object[] toArray() {
return delegate.toArray();
}
@Override
public <T1> T1[] toArray(T1[] a) {
return delegate.toArray(a);
}
@Override
public boolean add(T t) {
int i=0;
for(; i < delegate.size(); i++) {
if(order.compare(t, delegate.get(i)) < 0) {
break;
}
}
delegate.add(i, t);
return true;
}
@Override
public boolean remove(Object o) {
return delegate.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends T> c) {
if (c!= null && !c.isEmpty()) {
return c.stream().map(this::add).reduce(Boolean.FALSE, (l, r) -> l || r);
}
return false;
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
throw new IllegalStateException("Can only add in order");
}
@Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public T get(int index) {
return delegate.get(index);
}
@Override
public T set(int index, T element) {
throw new IllegalStateException("Can only add in order");
}
@Override
public void add(int index, T element) {
throw new IllegalStateException("Can only add in order");
}
@Override
public T remove(int index) {
return delegate.remove(index);
}
@Override
public int indexOf(Object o) {
return delegate.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return delegate.lastIndexOf(o);
}
@Override
public ListIterator<T> listIterator() {
return delegate.listIterator();
}
@Override
public ListIterator<T> listIterator(int index) {
return delegate.listIterator(index);
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return new SortedList<>(delegate.subList(fromIndex, toIndex), order);
}
@Override
public String toString() {
return delegate.toString();
}
}
Which you'll instantiate for instance for a sorted integers list, like this:
SortedList<Integer> nums =
new SortedList<Integer>(new ArrayList<Integer>(), Comparator.naturalOrder());
Alternatively, you could define your own data structure, say User
. Then it goes something like this:
public class User {
private String name;
private String time;
// getters and setters
}
Main advantages to using a data structure as opposed to Map<String, String>
include:
Map
, simply a list of User
type elements), Map
works but it is as simple as adding a field "location" to the data structure). Map<String, String>
doesn't say much about what it holds or what it is used for. Conversely, List<User>
can be immediately identified as a list of users. " User
" may not be the right name for the type, but the concept applies nonetheless.
You could load a list with Map.Entry:
final List<Map.Entry<String,String>> listOfEntries =
new ArrayList<>();
listOfEntries.add(new AbstractMap.SimpleEntry<>("Name", "01:01"));
listOfEntries.add(new AbstractMap.SimpleEntry<>("Name2", "05:10"));
Alternatively, you could load this list with Maps.immutableEntry("firstValue", "secondValue")
if you have a Guava dependency.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.