Quick way to search through arrayList - java

I have an arraylist Arraylist<String[]> and I am trying to find a quick way of looking for a specific value on a specific index of the String[]. My ArrayList is always going to contain String[] of length 2. And what I want to do is look through the ArrayList for any String[] that has a specific value i.e. str[1]="value". I know that I can iterate through the ArrayList taking every single element (String[]) and then looking for the value using str[1].equals("value") but I was wondering if there is a quicker way of doing it by maybe using contains() of the ArrayList or something.
thanks
PS: I don't know the value of the first element of my array (str[0]) so I cannot construct a new String[] and check if the ArrayList contains that

If you look into ArrrayList#contains - you will see, that this method also iterates through all elements.
You could use a parallelStream - so that the ArrayList can be searched by more threads.
List<String[]> listToSearchIn = new ArrayList<String[]>();
List<String[]> matches = listToSearchIn.parallelStream()
.filter((element) -> element[1].equals("value"))
.collect(Collectors.toList());

LinkedHashMap
How about using a LinkedHashMap<String, String[]> instead of the ArrayList? The key would be the String[1] value. Linked because that gives you predictable iteration order.
An auxiliary Map
Or you could create a Map<String, Integer> where the key is the String[1] value and the value is the index of your String[] in the ArrayList.
ArrayList<String[]> al = new ArrayList<>();
Map<String, Integer> alIndexMap = new HashMap<>();
// ...
Integer nextIndex = al.size();
al.add(someStringArray);
alIndexMap.put(someStringArray[1], nextIndex);
If you keep al and alIndexMap in sync all the time, you'll always know where in al is the array that you're looking for.
Guava BiMap
Google's Guava has some classes that implement their BiMap interface. It's like a Map, but it works both ways, i.e. you can use the value as a key if you want.

Unless your ArrayList is sorted then O(n) efficiency is the best you can do. Unless by "quick way" you mean a method which does the iteration for you. Even in this scenario the answer is no since you're wanting to check data inside the String[] objects themselves.

Related

Best way to check a list of values present in a map

I have a Collection containing some values.
Collection<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("b");
myList.add("c");
I created a Map which has some values:
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("r", "r");
myMap.put("s","m");
myMap.put("t", "n");
myMap.put("a", "o");
I want to check whether the values in the list are present as a key in the map? The way which I know using Java is to iterate through the list and check if the map contains that particular value using myMap.containsKey(). I want to know if there is anything out there using streams or for-each which saves me either lines of code or an efficient way of doing that! Thanks for thinking through it.
EDIT:
I want to store all the elements present in the myList which are not there in myMap. So my output can be a list e.g in this scenario [b,c].
Set<String> mySet = new HashSet<String>(myList);
myMap.keySet().containsAll(set);
Does this answer your question?
After your EDIT: Given the above, you can get the keys difference between two sets using the answer to one of these questions:- What is the best way get the symmetric difference between two sets in java? or Getting the difference between two sets
...whether the values in the list are present as a key in the map?
As I understand this case as you need to verify whether all the elements in the myList are present as the myMap's keys. Use the Stream::allMatch method:
myMap.keySet().stream()
.allMatch(myList::contains);
... which is the same as:
myList.keySet().containsAll(myMap);
EDIT: I want to store all the elements present in the myList which are not there in myMap. So my output can be a list e.g in this scenario [b,c].
You don't want to store all the elements in the myList since they are already there filled. You want to retain those elements using List::retainAll.
myList.retainAll(myMap.keySet());
Printing out the result of myList would produce only the keys, that have been found in the original myList and also as a key of myMap.
Using Streams you can do something like:
List<String> result = myList.stream()
.filter(myMap::containsKey)
.collect(Collectors.toList());
The resulting list will contain the values that are present as key in the map.
In case you want to print them out you can do:
result.forEach(System.out::println);
For: I want to store all the elements present in the myList which are
not there in myMap. So my output can be a list e.g in this scenario
[b,c]
Create a duplicate myList and remove all myMap's keys
Collection<String> newList = new ArrayList<>(myList);
newList.removeAll(myMap.keySet());
System.out.println(newList);

How to initiate multidimensional arraylist with different objects?

I'm having trouble trying to initiate an arraylist in which the first column I want to be a string, and the second column be a custom object.
For example column [0] be String, and column[1] be an Integer. Convention attempts of creating a multidimensional arraylist as in those used by int[][] or String[][] don't seem to work :( I would welcome any help. At this point I don't think it's something java allows. I can make it work for just one type of object but it's not what I want. Thanks!
Do you need an arraylist? You could create a Map<String, Object> or Map<String, Integer> or whatever you need..
Sure it does, but you weaken/eliminate type-checking:
Map myMap<String>, Integer> myData = new HashMap<String, Integer>();
Now your list of strings can be retrieved by myMap.keySet() and values can be retrieved by myMap.values(). Each of these return a Set, which you can easily convert to a List using the following code:
List<String> strings = new ArrayList<String>(myMap.keySet()); // get your strings
List<Integer> numbers = new ArrayList<Integer>(myMap.values(); // get your numbers
Good luck and if you should run into problems, do leave a comment.
Arrays are geared towards one specific type of thing - be they Object or String or int. Despite the fact that you're adding multiple dimensions to them, they still only hold one type of information.
What you would rather have is a mapping between two objects. This allows you to do the following:
Associate any key to a particular value
Eliminate duplicate key entries
Be much easier to access instead of array indexing
Here's an example. Say your custom object is a Cat, and you want to map the name of the owner to a particular Cat. You create a new instance of a Map.
Map<String, Cat> catOwners = new HashMap<>();
You can then put elements into it...
catOwners.put("Jamie", new Cat("Tycho"));
...and retrieve them with relative ease.
Cat currentCat = catOwners.get("Jamie"); // gets Jamie's cat
if you really want to, you can even iterate over them using the Map.Entry object provided with all Maps:
for(Map.Entry<String, Cat> element : catOwners.entrySet()) {
System.out.println(element.getKey()
+ " owns " + element.getValue().getName());
}
What you can do is use the generic Object type, and cast accordingly.

sort a map that contains an array of objects

if i make a map like this:
Map<Object, ArrayList<Object>> multiMap = new HashMap<Object, ArrayList<Object>>();
is there a way for me to sort on the values in the ArrayList<Object>?
i was thinking of just looping through the multimap as such:
for (Entry<Object, ArrayList<Object>> entry : multiMap.entrySet()) {
for (int i = 0; i < entry.size(); i++) {
//retrieve all array items and place in new array to sort
}
so we have
object ---> arrayList (contains 2 elements)
object ---> arrayList (contains 2 elements)
object ---> arrayList (contains 2 elements)
object ---> arrayList (contains 2 elements)
i want to take all the elements in all of the arrayLists above and sort by those. it doesn't need to stay in the multimap.. i was just looking to see if there was a better way to do it..
EDIT:
the point here is to sort all the array elements in every arrayList against all the other array elements in every other arrayList.... so it's not as simple as just calling sort
but i'm wondering if there is a better/cleaner way of doing this? i'm not all that familiar with maps... any help would be appreciated..
Based on your edit, you seem to want to get all the Objects in your Map and sort them. There is not a direct way to sort the values in a map together so to sort all the items, the easiest would be to consolidate them into one list and Collections.sort() the whole thing.
public ArrayList<Object> sortAllValues() {
ArrayList<Object> allEntries = new ArrayList<Object>();
for (Entry<Object, ArrayList<Object>> entry : multiMap.entrySet())
allEntries.addAll(entry.getValue());
}
return Collections.sort(allEntries);
}
You will still need to implement Comparable to your Object if it does not have it. This is a good guide on how to do implement Comparable
Actually you should not care that the ArrayList is the value in a Map this does not matter. You would sort this ArrayList<Object> just the way you would sort any such list. Problem here is that you will have to implement some kind of Comparator that casts the Object to the needed type. In general I would personally make the ArrayList of more specific type than Object to make sorting easier.
Check out the MultiMap implementations of Apache Commons and Google Collections. They might have one that already supports sorting/ordering.

How to sort map inside of List in java

List<Map<String,String>> consolidErr = new LinkedList<Map<String,String>>();
Map m1= new HashMap<String,String>();
m1.put("id","1");
m1.put("value","value1");
Map m2= new HashMap<String,String>();
m2.put("id","2");
m2.put("value","value2");
Map m3= new HashMap<String,String>();
m3.put("id","3");
m3.put("value","value3");
add all m1,m3 and m2 in list
then sort maps based on ids in map now i want maps in list as m1,m2 and m3.
Now I want to sort based on the ids in the map, I did that using iteration of list and keep first id of map as checker and compare with next it works if there any other better way than that using built-in methods.?Please give your ideas.am using bubble sort for this now.
The simplest way to do this in java (or at least, with the least mess) is to use a custom comparator.
The idea is that if you have objects with a natural sort (anything that extends Comparable) you can just ask for the sorting , e.g.
Collections.sort(List<Integer> ..
otherwise you can just pass in a Comparator that describes how you want objects compared, with any custom logic you want, e.g. (roughly - this is off the top of my head and doesn't have error checking, but should be enough to give you the idea) -
List<Map<String,String>> consolidErr = ...
enter code here
Collections.sort(consolidErr, new Comparator<Map<String,String>>(){
public int compare(Map<String,String> a, Map<String,String> b){
return a.get("id").compareTo(b.get("id"));}
})
In Java 8, we can sort the list of maps in a single line.
list.sort(Comparator.comparing((Map<String,String> mp) -> mp.get("Id")));
I would use instead the PriorityQueue
as a wrapper for your list. By providing the Comparator to the constructor when creating it, would assure you that your list will remain sorted after each insertion of a new element to the list.

Multidimensional Array with different types in java

I want to store a data structure thats a table with one column Strings and another column of Ints.
List<Entry<String, Integer>> li = new LinkedList<Entry<String, Integer>>();
would do the job for a list but I would rather have the performance of and need the memory of an array.
I tried
Entry<String, Integer>[] = new Entry<String, Integer>[10];
but that doesn't seem to work.
Is Entry the right datatype to use?
Write a class that represents your tuple and use an array (or a List) of that type. Don't eschew classes, they are your friends!
And what exactly do you mean by "the performance of an array"? Arrays are not necessarily faster than List implementations.
Think of inserting an element at the position 0: A LinkedList can do it in O(1). To get the same effect in an array, you'd have to do an O(n) operation (recreating the array and copying all existing values).
If you really need an array of generic types, you can do this:
Entry<String, Integer>[] array = new Entry[10];
It gives you a compilation warning though. You can read more about it here:
http://www.devarticles.com/c/a/Java/Wildcards-Arrays-and-Generics-in-Java/2/
I don't know what is not working, but:
you have to give a name to your array.
you can't construct arrays with generic types
don't forget Entry is an interface.
So, this:
Entry<String, Integer>[] = new Entry<String, Integer>[10];
Should be this:
Entry<String, Integer>[] entries = new Entry[10];
Hope this helps!
Maybe you can just use ArrayList, shouldn't be much difference in performance compared to a plain array.
Use this,
List<Entry<String, Integer>> li = new ArrayList<Entry<String, Integer>>();

Categories

Resources