I have two list of strings.
I want to check if any string from one list is available in another list.
Have used below approach which fails.
Please let me know a better approach
List<String> mylist = Arrays.asList(stringArray1);
List<String> items = Arrays.asList(stringArray2);
return mylist.stream().anyMatch(t->items.stream().anyMatch(t::contains));
If you want to find if any element in mylist exists in items, you can first turn items into a Set:
Set<String> setOfItems = new HashSet<>(items);
Then, you can simply iterative over mylist and check if any element is contained in setOfItems.
mylist.stream().anyMatch(setOfItems::contains);
This brought your O(n * k) problem down to O(n + k) where n and k are the sizes of mylist and items, respectively.
Related
It has been a long since something came to my mind while starting to code and using lists or array lists. When comparing values of one array to every other elements in another array, I used to do it in two for loops since it was the easiest way to do that.but recently I came to know that it increases much time complexity, I thought about another solution.can anyone help me in solving this case using any algorithm. I am using java.but solution in any language would be fine. just the algorithm to do that is needed. Thanks in advance.
This is what i am doing:
a1 = [1,2,3,4,5]
b1 = [9,5,4,3,8,3,7]
I want to check how much time an element in a1 occurs in b1
So what i am doing is:
count = 0;
for(int i = 0;i <a1.length;i++)
{
for(j=0;j<b1.length;j++)
{
if (a1[i] == b1[j])
{
count = count+1;
}
}
}
print("count is" count);
Theres no need of loop to obtain what you want
ArrayList<Integer> l1 = new ArrayList<Integer>();
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
ArrayList<Integer> l2 = new ArrayList<Integer>();
l2.add(9);
l2.add(5);
l2.add(4);
l2.add(3);
l2.add(8);
l2.add(3);
l2.add(7);
ArrayList<Integer> lFiltered = new ArrayList<Integer>(l2);
lFiltered.removeAll(l1);
int Times = l2.size() - lFiltered.size();
System.out.println("number of migrants : " + Times);
Suffice it to to generate from l2 a list without elements and l1 and to count elements which have been removed
Use hashing, e.g. using a Set or Map
If you want to compare the objects as a whole:
properly implement equals and hashcode for your class (if not implemented already)
put all the elements of list A into a Set, then see which elements from list B are in that Set
If you just want to compare objects by some attribute:
define a method that maps the objects to that attribute (or combination of attriutes, e.g. as a List)
create a Map<KeyAttributeType, List<YourClass>> and for each element from list A, add the element to that Map: map.get(getKey(x)).add(x)
for each element from list B, calculate the value of the key function and get the elements it "matches" from the map: matches = map.get(getKey(y))
Given your code, your case seems to be a bit different, though. You have lists or arrays of numbers, so no additional hashing is necessary, and you do not just want to see which items "match", but count all combinations of matching items. For this, you could create a Map<Integer, Long> to count how often each element of the first list appears, and then get the sum of those counts for the elements from the second list.
int[] a1 = {1,2,3,4,5};
int[] b1 = {9,5,4,3,8,3,7};
Map<Integer, Long> counts = IntStream.of(b1).boxed()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println(counts); // {3=2, 4=1, 5=1, 7=1, 8=1, 9=1}
long total = IntStream.of(a1).mapToLong(x -> counts.getOrDefault(x, 0L)).sum();
System.out.println(total); // 4
Of course, instead of using the Stream API you can just as well use regular loops.
Use ArrayLists.
To compare the content of both arrays:
ArrayList<String> listOne = new ArrayList<>(Arrays.asList(yourArray1);
ArrayList<String> listTwo = new ArrayList<>(Arrays.asList(yourArray);
listOne.retainAll(listTwo);
System.out.println(listOne)
To find missing elements:
listTwo.removeAll(listOne);
System.out.println(listTwo);
To enumerate the Common elements:
//Time complexity is O(n^2)
int count =0;
for (String element : listOne){
for (String element2: listTwo){
if (element.equalsIgnoreCase(elemnt2){
count += 1;
}
}
}
I've two ArrayList both containing Integer values. My objective is to get identical/common/duplicate values comparing these 2 list. In other words (in SQL parlance), I need the INTERSECT result of two lists, that is, values that appear in both list.
Example:
ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(100);
list1.add(200);
list1.add(300);
list1.add(400);
list1.add(500);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(300);
list2.add(600);
One kind of implementation/solution I could think along is looping one of the list something like:
ArrayList<Integer> intersectList = new ArrayList<Integer>();
for (Integer intValue : list1)
{
if(list2.contains(intValue))
intersectList.add(intValue);
}
In this case, intersectList would contain only 1 Integer item being added, that is 300, which appears in both list.
My question is, are there any better/fastest/efficient way of implementing this logic? Any options available in Apache Commons library?. Any other ideas/suggestions/comments are appreciated.
NOTE: For illustration purpose, I've just shown here 5 items and 2 items being added into the list. In my real-time implementation, there will be more than 1000 elements in each list. Therefore, performance is also a key factor to be considered.
If you're okay with overwriting result for list1:
list1.retainAll(list2);
otherwise clone/copy list1 first.
Not sure on performance though.
list1.retainAll(list2)//for intersection
Use ListUtils from org.apache.commons.collections if you do not want to modify existing list.
ListUtils.intersection(list1, list2)
I have a bunch of indexes and I want to remove elements at these indexes from an ArrayList. I can't do a simple sequence of remove()s because the elements are shifted after each removal. How do I solve this?
To remove elements at indexes:
Collections.sort(indexes, Collections.reverseOrder());
for (int i : indexes)
strs.remove(i);
Or, using the Stream API from Java 8:
indexes.sort(Comparator.reverseOrder());
indexes.stream().mapToInt(i -> i).forEach(l::remove);
Sort the indices in descending order and then remove them one by one. If you do that, there's no way a remove will affect any indices that you later want to remove.
How you sort them will depend on the collection you are using to store the indices. If it's a list, you can do this:
List<Integer> indices;
Collections.sort(indices, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
//todo: handle null
return b.compareTo(a);
}
}
Edit
#aioobe found the helper that I failed to find. Instead of the above, you can use
Collections.sort(indices, Collections.reverseOrder());
I came here for removing elements in specific range (i.e., all elements between 2 indexes), and found this:
list.subList(indexStart, indexEnd).clear()
You can remove the elements starting from the largest index downwards, or if you have references to the objects you wish to remove, you can use the removeAll method.
you might want to use the subList method with the range of index you would like to remove and
then call clear() on it.
(pay attention that the second parameter is exclusive - for example in this case, I pass 2 meaning only index 0 and 1 will be removed.):
public static void main(String[] args) {
ArrayList<String> animals = new ArrayList<String>();
animals.add("cow");
animals.add("dog");
animals.add("chicken");
animals.add("cat");
animals.subList(0, 2).clear();
for(String s : animals)
System.out.println(s);
}
}
the result will be:
chicken
cat
You can remove the indexes in reverse order. If the indexes are in order like 1,2,3 you can do removeRange(1, 3).
I think nanda was the correct answer.
List<T> toRemove = new LinkedList<T>();
for (T t : masterList) {
if (t.shouldRemove()) {
toRemove.add(t);
}
}
masterList.removeAll(toRemove);
You can sort the indices as many said, or you can use an iterator and call remove()
List<String> list = new ArrayList<String>();
list.add("0");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
List<Integer> indexes = new ArrayList<Integer>();
indexes.add(2);
indexes.add(5);
indexes.add(3);
int cpt = 0;
Iterator<String> it = list.iterator();
while(it.hasNext()){
it.next();
if(indexes.contains(cpt)){
it.remove();
}
cpt++;
}
it depends what you need, but the sort will be faster in most cases
Use guava! The method you are looking is Iterators.removeAll(Iterator removeFrom, Collection elementsToRemove)
If you have really many elements to remove (and a long list), it may be faster to iterate over the list and add all elements who are not to be removed to a new list, since each remove()-step in a array-list copies all elements after the removed one by one. In this case, if you index list is not already sorted (and you can iterate over it parallel to the main list), you may want to use a HashSet or BitSet or some similar O(1)-access-structure for the contains() check:
/**
* creates a new List containing all elements of {#code original},
* apart from those with an index in {#code indices}.
* Neither the original list nor the indices collection is changed.
* #return a new list containing only the remaining elements.
*/
public <X> List<X> removeElements(List<X> original, Collection<Integer> indices) {
// wrap for faster access.
indices = new HashSet<Integer>(indices);
List<X> output = new ArrayList<X>();
int len = original.size();
for(int i = 0; i < len; i++) {
if(!indices.contains(i)) {
output.add(original.get(i));
}
}
return output;
}
order your list of indexes, like this
if 2,12,9,7,3 order desc to 12,9,7,3,2
and then do this
for(var i = 0; i < indexes.length; i++)
{
source_array.remove(indexes[0]);
}
this should resolve your problem.
If the elements you wish to remove are all grouped together, you can do a subList(start, end).clear() operation.
If the elements you wish to remove are scattered, it may be better to create a new ArrayList, add only the elements you wish to include, and then copy back into the original list.
Edit: I realize now this was not a question of performance but of logic.
If you want to remove positions X to the Size
//a is the ArrayList
a=(ArrayList)a.sublist(0,X-1);
Assuming your indexes array is sorted (eg: 1, 3, 19, 29), you can do this:
for (int i = 0; i < indexes.size(); i++){
originalArray.remove(indexes.get(i) - i);
}
A more efficient method that I guess I have not seen above is creating a new Arraylist and selecting which indices survive by copying them to the new array. And finally reassign the reference.
I ended up here for a similar query and #aioobe's answer helped me figure out the solution.
However, if you are populating the list of indices to delete yourself, might want to consider using this:
indices.add(0, i);
This will eliminate the need for (the costly) reverse-sorting of the list before iterating over it, while removing elements from the main ArrayList.
I have 9 different ArrayList and I want to have a list of the top 5.
I'm thinking of sorting those ArrayLists by their sizes.
Is it possible to do that? If so, how can I achieve that?
After a few try i finally got it working, just want to share it with everyone.
it will be better to get the size of the arraylist and add it to the big arraylist
// creates an ArrayList that holds ArrayLists
List allTheLists = new ArrayList();
allTheLists.add(pbaustraliaList.size());
allTheLists.add(pbotherList.size());
allTheLists.add(pbunitedStatesList.size());
allTheLists.add(pbunitedKingdomList.size());
allTheLists.add(pbchinaList.size());
allTheLists.add(pbgermanyList.size());
allTheLists.add(pbindiaList.size());
allTheLists.add(pbjapanList.size());
allTheLists.add(pbsingaporeList.size());
Comparator comparator = Collections.reverseOrder();
Collections.sort(allTheLists,comparator);
//display elements of ArrayList
System.out.println("ArrayList elements after sorting in descending order : ");
for(int i=0; i<allTheLists.size(); i++) {
System.out.println(allTheLists.get(i));
}
What you could do is the following:
// this List of lists will need to contain
// all of the ArrayLists you would like to sort
List<ArrayList> allTheLists;
Collections.sort(allTheLists, new Comparator<ArrayList>(){
public int compare(ArrayList a1, ArrayList a2) {
return a2.size() - a1.size(); // assumes you want biggest to smallest
}
});
This will sort the list of lists by the length of each list. The first element in the sorted list will be the longest list, and the last one will be the shortest list.
Then, you can iterate through the first 5 lists to see what the top 5 were.
Some links for reference:
Sorting tutorial
Collections Javadoc
Comparator Javadoc
Depending on how you have your ArrayLists stored, the code to create a List<ArrayList> would look something like this:
// creates an ArrayList that holds ArrayLists
List<ArrayList> allTheLists = new ArrayList<ArrayList>();
allTheLists.add(yourList1);
allTheLists.add(yourList2);
...
allTheLists.add(yourList9);
you can do like this as well
public static <T> List<List<T>> sort(List<List<T>> list) {
list.sort((xs1, xs2) -> xs1.size() - xs2.size());
return list;
}
The sort method that's available on a List needs a Comparator. That comparator can be created with the Comparator.comparing method, with additional special implementations including for extracting and comparing an int - Comparator.comparingInt.
import static java.util.Comparator.comparingInt;
...
List<List<Integer>> listOfLists = ...
listOfLists.sort(comparingInt(List::size));
List::size will map a List to an int (the size of the list) and use that to create a new Comparator that can be used for our sorting purposes.
If you want largest first
listOfLists.sort(comparingInt(List::size).reversed());
Dump the top 5 (switching over to Java 8 streams):
listOfLists.stream()
.sorted(comparingInt(List::size).reversed())
.limit(5)
.forEachOrdered(System.out::println);
This was the question asked in interview.Can anybody help me out it in implementing in java
Given 2 linked lists(which need not have unique elements) find intersection point in the form of Y.(it can be anywhere--middle or tail)
If the length of the lists is O(N), this solution is O(N) with O(1) space.
FUNCTION length(LIST list) : INT
// returns number of nodes until the end of the list
FUNCTION skip(LIST list, INT k) : LIST
// return the sublist of list, skipping k nodes
FUNCTION intersection(LIST list1, list2) : LIST
// returns the sublist where the two lists intersects
INT n1 = length(list1);
INT n2 = length(list2);
IF (n1 > n2) THEN
list1 = skip(list1, n1-n2)
ELSE
list2 = skip(list2, n2-n1)
WHILE (list1 != list2)
list1 = skip(list1, 1)
list2 = skip(list2, 1)
RETURN list1
Essentially, traverse each lists to find how many nodes there are. Then, skip enough elements from the longer list so that now you have lists of the same length. Then, in-sync, move forward step-by-step until the two lists meet.
http://java.sun.com/docs/books/tutorial/collections/interfaces/set.html
I don't have a good example at the moment, but I believe he's referring to this:
"The intersection of two sets is the set containing only the elements common to both sets."
Where 'sets' can also be Lists, etc.
Java has built in methods for this.
Say you have a List list, you would do something like this:
list.removeAll(list2);
or
list.retainAll(list2);
retainAll will you give you the 'intersection', removeAll gives you the difference between the two lists.
According to #Lord Torgamus question, here is a suggested java algorithm.
Suppose you have two java Collection objects (and LinkedList, as an implementor of List, is also an implementor of Collection). To find their intersection, you only have to call Collection#retainAll method on the first object giving the second one as an argument.