Accessing Iterable Object directly - java

I get a iterable list which I iterate using following code
for (IssueField issueObj : issue.getFields())
{
System.out.println(issueObj.getId());
}
the list is of following structure
[IssueField{id=customfield_13061, name=Dev Team Updates, type=null, value=null},
IssueField{id=customfield_13060, name=Development, type=null, value={}},
IssueField{id=customfield_11160, name=Rank, type=null, value=1|i0065r:},
IssueField{id=customfield_13100, name=TM Product, type=null, value=IntelliGlance},
IssueField{id=customfield_11560, name=Release Notes, type=null, value=null},
IssueField{id=customfield_13500, name=Request Type, type=null, value=null},
IssueField{id=customfield_13900, name=Category, type=null, value=null},
IssueField{id=environment, name=Environment, type=null, value=null}]
there are more then 100 of such objects in the list. is there a way I can directly get the desired objects value without iterating all the values. currently using something like this which I think is not efficient.
for (IssueField issueObj : issue.getFields())
{
if(issueObj.getId().equalIgnoreCase(someId)){
//Object Found
}
}

If you want to be able to do frequent searching over a large dataset like you said then you should use a HashMap where the string is the value in your getId(). The big O time complexity for search of a HashMap is O(1) where for a list it is O(n). This would net you the desired efficiency.

If you are using java 8, You can try this
<your-object> result1 = <your-list>.stream()
.filter(x -> "jack".equals(x.getId()))
.findAny()
.orElse(null);
First of all it Convert list to Streams, then you want id like "jack", If 'findAny' then return object otherwise return null

If you don't want to iterate the hole Collection to get the desired object, you need to store the objects in the most suitable collection, so if you want to get an element by its id i think the most efficient way is by using a Hashmap , then you use the get function to retrieve the desired element.
HashMap implementation provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets. Iteration over collection views requires time proportional to the "capacity" of the HashMap instance (the number of buckets) plus its size (the number of key-value mappings). Thus, it's very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.
Source

Related

Update a single object from a list using stream

I have a list of objects. I need to update a single object from the list that match my filter. I can do something like below:
List<MyObject> list = list.stream().map(d -> {
if (d.id == 1) {
d.name = "Yahoo";
return d;
}
return d;
});
But my worry is i am like iterating through the whole list which may be up to 20k records. I can do a for loop then break, but that one I think also will be slow.
Is there any efficient way to do this?
Use findFirst so after finding the first matching element in the list remaining elements will not be processed
Optional<MyObject> result = list.stream()
.filter(obj->obj.getId()==1)
.peek(o->o.setName("Yahoo"))
.findFirst();
Or
//will not return anything but will update the first matching object name
list.stream()
.filter(obj->obj.getId()==1)
.findFirst()
.ifPresent(o->o.setName("Yahoo"));
You can use a Map instead of a list and save the id as a key.
https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
Then you can extract it with O(1).
It depends on how often you need to perform this logic on your input data.
If it happens to be several times, consider using a Map as suggested by Raz.
You can also transform your List into a Map using a Stream:
Map<Integer, MyObject> map = list.stream()
.collect(Collectors.toMap(
MyObject::getId
Function.identity()
));
The first argument of toMap maps a stream item to the corresponding key in the map (here the ID of MyObject), and the second argument maps an item to the map value (here the MyObject item itself).
Constructing the map will cost you some time and memory, but once you have it, searching an item by ID is extremely fast.
The more often you search an item, the more constructing the map first pays off.
However, if you only ever need to update a single item and then forget about the whole list, just search for the right element, update it and you're done.
If your data is already sorted by ID, you can use binary search to find your item faster.
Otherwise, you need to iterate through your list until you find your item. In terms of performance, nothing will beat a simple loop here. But using Stream and Optional as shown in Deadpool's answer is fine as well, and might result in clearer code, which is more important in most cases.
.stream().peek(t->t.setTag(t.getTag().replace("/","")));
Do anything you want with peek() meyhod

ArrayMap put method pushes elements in strange order

I am using ArrayMap for first time in my project and I thought it works just like an array. I expected when I use .put method it inserts it at next index.
But in my case this is not true - after I added all elements one by one the first element I added ended up at index 4 which is kind of strange.
Here are the first three steps which I add elements:
1 - Salads:
2 - Soups:
3 - Appetizers:
So somehow on second step "Soup" element was inserted in index 0 instead of 1 as I was expecting, but strangely on third step "Appetizers" was inserted as expected after "Soup".
This is the code I am using to push key and value pair:
function ArrayMap<String, DMType> addElement(String typeKey, DMType type) {
ArrayMap<String, DMType> types = new ArrayMap<>();
types.put(typeKey, type);
return types;
}
Am I missing something about the behavior of ArrayMap?
Yeah it is misleading because of the name but ArrayMap does no gurantee order unlike arrays.
ArrayMap is a generic key->value mapping data structure that is
designed to be more memory efficient than a traditional HashMap.
ArrayMap is actually a Map:
public class ArrayMap extends SimpleArrayMap implements Map
If you want the Map functionality with order guranteed use LinkedHashMap instead.
LinkedHashMap defines the iteration ordering, which is normally the
order in which keys were inserted into the map (insertion-order).
documentation
I thought it works just like an array
No, it works like a map, because it is a map. It is similar to a HashMap, but more memory efficient for smaller data sets.
It's order shouldn't and doesn't matter. Under the hood, it is implemented using
an array which has an order since arrays do. This inherently gives the ArrayMap an order, but that is not part of it's API anyway. Just like which memory slot your Java objects are in, you shouldn't care about the order here either.
It doesn't work as an array, I don't see Array in the name but Map and the documentation clearly states that behaves as a generic key->value mapping, more efficient (memory wise) than traditional HashMap implementation.
Actually I don't see why you care about the order compared to the insertion one. Data is private inside the class and you have no way to obtain the element by the index, so you are basically wondering about a private implementation which is irrelevant for its usage.
If you really want to understand how it stores its data you should take a look at the source code.
ArrayMap does NOT work like an Array, instead, it works like a HashMap with performance optimizations.
The internal sequence of the key-value pair is not guaranteed as it is NOT part of the contract.
In your case, what you really want to use is probably an ArrayList<Element>, where the Element class is defined like this:
public class Element{
private final String typeKey;
private final DMType type;
public Element(String typeKey, DMType type){
this.typeKey = typeKey;
this.type = type;
}
}
If you don't want a new Class just to store the result, and you want to keep the sequence, you can use a LinkedHashMap<String, DMType>. As the document specifies:
Class LinkedHashMap
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map. (A key k is reinserted into a map m if m.put(k, v) is invoked when m.containsKey(k) would return true immediately prior to the invocation.)

Search a Map for multiple keys in parallel

Given a Map<String, Collection<String>> up to 1M items. I know what to query that Map for 5K keys, of which I'm unsure whether they are in the map or not.
Currently, I'm using a TreeMap and search for each item, one by one. Which seems sub-optimal. Is there an, already, implemented way to query a Map for X keys?
The result of the search should be a subset of items, which are found in the Map, for further querying - ordering is irrelevant.
I was hoping to use stream, but, apparently, that's only for Collections.
Note: the number are impressions, from what I've seen in the map, probably not the upper limit...
There is no better way than querying your map for each element:
List<V> vs = keysToSearch.stream()
.map(k -> map.get(k))
.filter(Objects::nonNull)
.collect(Collectors.toList())
You can also try using a parallelStream if your data structures work in a concurrent environment.
assuming memory is not a problem for you. here is one way of doing it.
by using retainAll
Set<String> mapKeys = new HashSet<String>(myMap.keySet());
mapKeys.retainAll(my5kKeys); //<--- all keys that match the my5kKeys...
If you have M items in your map, and K keys you are searching for, then your best-case efficiency is O(min(M, K)). If M is very large, the best you can do is to check each K (perhaps in parallel, but you must do each).
If it were the case that M turned out to be much smaller than K, then you could do better by only checking through all M values to see if they existed in K. In any event, you want to check the smaller set's values against the larger.
There is no better way then to create a loop and search for all the keys individually.
A method like retainAll is just a wrapper around such a loop written by somebody else.
However, the important thing is to use a HashMap instead of a TreeMap. Hashmaps contains is O(1) while Treemap takes O(log(n)).
If you need the sorted collection for something else, you could put the data in both a TreeMap and a HashMap.

How list differ from map?

In java, List and Map are using in collections. But i couldn't understand at which situations we should use List and which time use Map. What is the major difference between both of them?
Now would be a good time to read the Java collections tutorial - but fundamentally, a list is an ordered sequence of elements which you can access by index, and a map is a usually unordered mapping from keys to values. (Some maps preserve insertion order, but that's implementation-specific.)
It's usually fairly obvious when you want a key/value mapping and when you just want a collection of elements. It becomes less clear if the key is part of the value, but you want to be able to get at an item by that key efficiently. That's still a good use case for a map, even though in some senses you don't have a separate collection of keys.
There's also Set, which is a (usually unordered) collection of distinct elements.
Map is for Key:Value pair kind of data.for instance if you want to map student roll numbers to their names.
List is for simple ordered collection of elements which allow duplicates.
for instance to represent list of student names.
Map Interface
A Map cares about unique identifiers. You map a unique key (the ID) to a specific
value, where both the key and the value are, of course, objects.
The Map implementations let you do things like search for a
value based on the key, ask for a collection of just the values, or ask for a collection
of just the keys. Like Sets, Maps rely on the equals() method to determine whether
two keys are the same or different.
List Interface
A List cares about the index. The one thing that List has that non-lists don't have
is a set of methods related to the index. Those key methods include things like
get(int index), indexOf(Object o), add(int index, Object obj), and so
on. All three List implementations are ordered by index position—a position that
you determine either by setting an object at a specific index or by adding it without
specifying position, in which case the object is added to the end.
list is a linked list, where every object is connected to the next one via pointers. the time it takes to insert a new object to the list is O(1) but the rest of operations on it take longer.
the good thing about it is that it takes exactly the amount of memory you need and not even on byte more than that.
Maps are a data structure that has an array and each entry to the array is calculated with a hashFunction(key) that calculates the location according to the key. almost every operation in a Map taks O(1) (except inserting when there are 2 identical keys) but the space complexity is fairly large.
for more reading try wikipedia's HashMap and linked list
HashList is a data structure storing objects in a hash table and a list.it is a combination of hashmap and doubly linked list. acess will be faster. HashMap is hash table implementation of map interface it is same as HashTable except that it is unsynchronized and allow null values. List is an ordered collection and it allow nulls and duplicates in it. positional acess is possible. Set is a collection that doesn't allow duplicates, it may allow at most one null element. same as our mathematical set.
List is just an ordered collectiom(a sequence). Check this list documentation .You can access elements by their integer index (position in the list), and search for elements in the list.
Also lists allow duplicate elements and multiple NULL elements.
Map is an object that maps the values to the keys. Check this map documentation. A map cannot contain duplicate keys; each key can map to at most one value.
List - This datastructure is used to contain list of elements.
In case you need list of elements and the list may contain duplicate values,
then you have to use List.
Map - It contains data as key value pair. When you have to store data
in key value pair,so that latter you can retrieve data using the key,
you have to use Map data structure.
List implementation - ArrayList, LinkedList
Map implementation - HashMap, TreeMap
In comparison HashMap to ArrayList -
A hash map is the fastest data structure if you want to get all nodes for a page. The list of nodes can be fetched in constant time (O(1)) while with lists the time is O(n) (n=number of pages, faster on sorted lists but never getting near O(1))

When to use HashMap over LinkedList or ArrayList and vice-versa

What is the reason why we cannot always use a HashMap, even though it is much more efficient than ArrayList or LinkedList in add,remove operations, also irrespective of the number of the elements.
I googled it and found some reasons, but there was always a workaround for using HashMap, with advantages still alive.
Lists represent a sequential ordering of elements.
Maps are used to represent a collection of key / value pairs.
While you could use a map as a list, there are some definite downsides of doing so.
Maintaining order:
A list by definition is ordered. You add items and then you are able to iterate back through the list in the order that you inserted the items. When you add items to a HashMap, you are not guaranteed to retrieve the items in the same order you put them in. There are subclasses of HashMap like LinkedHashMap that will maintain the order, but in general order is not guaranteed with a Map.
Key/Value semantics:
The purpose of a map is to store items based on a key that can be used to retrieve the item at a later point. Similar functionality can only be achieved with a list in the limited case where the key happens to be the position in the list.
Code readability
Consider the following examples.
// Adding to a List
list.add(myObject); // adds to the end of the list
map.put(myKey, myObject); // sure, you can do this, but what is myKey?
map.put("1", myObject); // you could use the position as a key but why?
// Iterating through the items
for (Object o : myList) // nice and easy
for (Object o : myMap.values()) // more code and the order is not guaranteed
Collection functionality
Some great utility functions are available for lists via the Collections class. For example ...
// Randomize the list
Collections.shuffle(myList);
// Sort the list
Collections.sort(myList, myComparator);
Lists and Maps are different data structures. Maps are used for when you want to associate a key with a value and Lists are an ordered collection.
Map is an interface in the Java Collection Framework and a HashMap is one implementation of the Map interface. HashMap are efficient for locating a value based on a key and inserting and deleting values based on a key. The entries of a HashMap are not ordered.
ArrayList and LinkedList are an implementation of the List interface. LinkedList provides sequential access and is generally more efficient at inserting and deleting elements in the list, however, it is it less efficient at accessing elements in a list. ArrayList provides random access and is more efficient at accessing elements but is generally slower at inserting and deleting elements.
I will put here some real case examples and scenarios when to use one or another, it might be of help for somebody else:
HashMap
When you have to use cache in your application. Redis and membase are some type of extended HashMap. (Doesn't matter the order of the elements, you need quick ( O(1) ) read access (a value), using a key).
LinkedList
When the order is important (they are ordered as they were added to the LinkedList), the number of elements are unknown (don't waste memory allocation) and you require quick insertion time ( O(1) ). A list of to-do items that can be listed sequentially as they are added is a good example.
The downfall of ArrayList and LinkedList is that when iterating through them, depending on the search algorithm, the time it takes to find an item grows with the size of the list.
The beauty of hashing is that although you sacrifice some extra time searching for the element, the time taken does not grow with the size of the map. This is because the HashMap finds information by converting the element you are searching for, directly into the index, so it can make the jump.
Long story short...
LinkedList: Consumes a little more memory than ArrayList, low cost for insertions(add & remove)
ArrayList: Consumes low memory, but similar to LinkedList, and takes extra time to search when large.
HashMap: Can perform a jump to the value, making the search time constant for large maps. Consumes more memory and takes longer to find the value than small lists.

Categories

Resources