how to find number which are not in a arraylist? - java

So I have a Arraylist. It is currently holding integers. I would like to get list of integers that are not in the arraylist from a certain range. For example if the range of numbers was from 1 to 5, if the arraylist contains 1,3,4 then the output should 2 and 5. The numbers stored in the ArrayList should also be unique hence I am thinking of using Hashset. This is my code so far:
HashSet<Integer> abc = new HashSet<>();
while(myrs.next()){
try {
//RoomIdsThatAreCurrentlyReserved.add(Integer.parseInt(myrs.getObject(1).toString()));
abc.add(Integer.parseInt(myrs.getObject(1).toString()));
} catch (SQLException e) {
e.printStackTrace();
My code is basically reading from a result set.

With Eclipse Collections, the following will work using MutableSet. Using MutableSet here since you seem to be open for using Set.
MutableSet<Integer> set = Sets.mutable.with(1, 2, 3, 4, 5);
MutableSet<Integer> anotherSet = Sets.mutable.with(2, 3, 4);
MutableSet<Integer> result = set.difference(anotherSet);
System.out.println(result); //[1, 5]
Note: I am a committer for Eclipse Collections.

Here is simple example :
Arraylist a={1,2,3,4,5};
Arraylist b={2,3,4};
if you won't an output like 1 and 5.
then
simply used this:
List<Integer> c = new ArrayList<>(a);
c.removeAll(b);

Why don't you do like this,
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
int currentIteratorValue = (int) iterator.next();
if(currentIteratorValue != 1 && currentIteratorValue != 3 && currentIteratorValue != 4){
System.out.println(currentIteratorValue); //Prints 5 and 2
}
}

It's a 1-liner.
Given:
List<Integer> list; // populated elsewhere
// copy to a set if the list is large so it will perform better
Set<Integer> set = new HashSet<>(list);
Then:
List<Integer> missing = IntStream.range(a, b)
.filter(i -> !set.contains(i))
.collect(Collectors.toList());
If the list is small you can skip the set and just use
.filter(i -> !list.contains(i))
but that is O(n) whereas the set contains is O(1).

Using https://github.com/google/guava (java 1.6)
List<Integer> fullList = Lists.newArrayList(1, 2, 3, 4 , 5);
List<Integer> partOfList = Lists.newArrayList(1, 3, 4 );
FluentIterable<Integer> missing = FluentIterable.from(fullList).filter(Predicates.not(Predicates.in(partOfList)));

Related

Correct order of elements of Cartesian product of ArrayLists

I tried to generate Cartesian product of unknown number of ArrayLists (of fixed type) based on this answer: Cartesian product of an arbitrary number of sets. But I have found something strange. The cartesian products is always given in reverse order. For example, if A and B are two Lists, B's elements are given first and A's elements are given second in cartesian pair. What could be possible reason? How to fix that? Original answerer says, ordering does not matter in Cartesian product. But I think ordering is the main thing while making cartesian products especially when each set represents coordinates of plane.
Modified Code:
private static Set<ArrayList<Double>> cartesianProduct(ArrayList<ArrayList<Double>> sets) {
if (sets.size() < 2)
throw new IllegalArgumentException(
"Can't have a product of fewer than two sets (got " +
sets.size() + ")");
return _cartesianProduct(0, sets);
}
private static Set<ArrayList<Double>> _cartesianProduct(int index, ArrayList<ArrayList<Double>> sets) {
Set<ArrayList<Double>> ret = new HashSet<>();
if (index == sets.size()) {
ret.add(new ArrayList<>());
} else {
for (Double obj : sets.get(index)) {
for (ArrayList<Double> set : _cartesianProduct(index + 1, sets)) {
set.add(obj);
ret.add(set);
}
}
}
return ret;
}
Output:
ArrayList<Double> l1 = new ArrayList<>(Arrays.asList(1.0, 2.0));
ArrayList<Double> l2 = new ArrayList<>(Arrays.asList(4.0, 5.0));
ArrayList<ArrayList<Double>> l = new ArrayList<>(Arrays.asList(l1, l2));
Set<ArrayList<Double>> a = cartesianProduct(l);
// a = [[4.0, 1.0], [4.0, 2.0], [5.0, 1.0], [5.0, 2.0]]
This method constructs the cartesian product in reverse because it creates the product "inside out" - when it's returning out of the recursion.
Printed out the value returned by each level in the recursion and you'll see how it happens.
The second level of recursion works on list B and returns [[4], [5]].
The first level of recursion takes [[4], [5]] and uses the list.add method to add items from the list A. This method adds items to the end of the list so the result is [[4, 1], [5, 1], [4, 2], [5, 2]].
How to fix it?
A quick fix is inserting items to the front, instead of to the back. Instead of set.add(obj) use:
set.add(0, obj);
Another option is to reverse the order of iteration so that the second level of recursion uses list A, and the first level uses list B. The initial call to start the recursion would be made from sets.size() and it should count down instead of up:
return _cartesianProduct(sets.size() - 1, sets);
...
for (ArrayList<Double> set : _cartesianProduct(index - 1, sets)) {
Yet another option is changing the recursion so that the product is built on the way down the recursion - "outside in" - instead of on the way out. This is the approach taken in another answer to the question you link to: https://stackoverflow.com/a/9496234/318758
This happens because of recursion. Index is initially 0, so at the line for (ArrayList<Double> set : _cartesianProduct(index + 1, sets)) {, your code calls cartesianProduct again with index=1. Again it reaches that line, and calls cartesianProduct with index=2. When it is at index=2, it reaches its base case and returns a set with an empty ArrayList.
Then it goes back to the stackframe where index=1 (remember,obj is 4.0 because sets.get(1) is the ArrayList containing 4 and 6). It adds all the doubles in sets.get(index) (here it is 4.0 and 6.0) to their own ArrayLists in ret. Then it reaches the end of the foreach loop and returns the set, which now has 2 ArrayLists, one containing a 4.0 and the other 6.0.
The same happens at index=0, so the first list(or set)'s elements are added after the second list's elements. That's why you get reverse results.
To fix this, you could decrement index every time, going from sets.size() to 0 instead of the other way around. To reverse it, you can also simply call Collections.reverse() on every set inside the result.
//Fix by decrementing index
private static Set<ArrayList<Double>> cartesianProduct(ArrayList<ArrayList<Double>> sets) {
if (sets.size() < 2)
throw new IllegalArgumentException(
"Can't have a product of fewer than two sets (got " + sets.size() + ")");
//Be sure to start at the end of 'sets' so you can go down by one
return cartesianProduct(sets.size() - 1, sets);
}
private static Set<ArrayList<Double>> cartesianProduct(int index, ArrayList<ArrayList<Double>> sets) {
Set<ArrayList<Double>> ret = new HashSet<>();
//Counting to 0 instead of to the end of the sets ArrayList
if (index < 0) {
ret.add(new ArrayList<>());
} else {
for (Double obj : sets.get(index)) {
for (ArrayList<Double> set : cartesianProduct(index - 1, sets)) {
set.add(obj);
ret.add(set);
}
}
}
return ret;
}
//Alternative answer using Collections.reverse
private static Set<ArrayList<Double>> cartesianProduct(ArrayList<ArrayList<Double>> sets) {
if (sets.size() < 2)
throw new IllegalArgumentException(
"Can't have a product of fewer than two sets (got " + sets.size() + ")");
//This basically goes through the set of sets and reverses each ArrayList
return cartesianProduct(0, sets).stream().map(Collections::reverse).collect(Collectors.toSet());
}
If order matters, you can rewrite your code as follows:
ArrayList<Double> l1 = new ArrayList<>(Arrays.asList(1.0, 2.0, 3.0));
ArrayList<Double> l2 = new ArrayList<>(Arrays.asList(4.0, 5.0, 6.0));
List<List<Double>> cartesianProduct = Stream.of(l1, l2)
// represent each list element as a singleton list
.map(list -> list.stream().map(Collections::singletonList)
// List<List<Double>>
.collect(Collectors.toList()))
// intermediate output
//[[1.0], [2.0], [3.0]]
//[[4.0], [5.0], [6.0]]
.peek(System.out::println)
// summation of pairs of inner lists
.reduce((list1, list2) -> list1.stream()
// combinations of inner lists
.flatMap(inner1 -> list2.stream()
// merge two inner lists into one
.map(inner2 -> Stream.of(inner1, inner2)
.flatMap(List::stream)
.collect(Collectors.toList())))
// list of combinations
.collect(Collectors.toList()))
// returns List<List<Double>>, otherwise an empty list
.orElse(Collections.emptyList());
// final output
cartesianProduct.forEach(System.out::println);
//[1.0, 4.0]
//[1.0, 5.0]
//[1.0, 6.0]
//[2.0, 4.0]
//[2.0, 5.0]
//[2.0, 6.0]
//[3.0, 4.0]
//[3.0, 5.0]
//[3.0, 6.0]
See also: Cartesian product of an arbitrary number of sets

java streams - How to filter a collection to two new collections

I tried to create two lists - odds and evens as follows:
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 8, 13, 21));
List<Integer> odds = new ArrayList<>();
List<Integer> evens = new ArrayList<>();
numbers.stream().forEach(x -> x % 2 == 0 ? evens.add(x) : odds.add(x));
}
But it gave me incompatible types error (bad return type in lambda expression
missing return value)
What is the best way to filter a collection to two new collections?
As the other answers explain why it doesn't compile I would use in your case the partitioningBy collector and fetch the resulting lists:
import static java.util.stream.Collectors.partitioningBy;
...
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 9, 13, 21);
Map<Boolean, List<Integer>> partition =
numbers.stream().collect(partitioningBy(x -> x % 2 == 0));
List<Integer> odds = partition.get(false);
List<Integer> evens = partition.get(true);
Well, you can make your existing code compile with a trivial modification:
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 8, 13, 21));
List<Integer> odds = new ArrayList<>();
List<Integer> evens = new ArrayList<>();
numbers.stream().forEach(x -> (x % 2 == 0 ? evens : odds).add(x));
}
The conditional ?: operator is an expression, which isn't a valid statement on its own. My modified code changes the use of the conditional operator to just select which list to add to, and then calls add on it - and that method invocation expression is a valid statement.
An alternative would be to collect using Collectors.partitioningBy - although in this particular case that would probably be more confusing code than what you've got.
A ternary operator is not a statement. If you're using a forEach block, you'd need a valid Java statement, or a complete block:
numbers.stream().forEach(x -> {
if (x % 2 == 0 ) {
pairs.add(x);
} else {
ods.add(x);
}
});

Combine values with Java8 stream

If I have a list with integers, is there a way to construct another list, where integers are summed if the difference to the head of the new list is below a threashold? I would like to solve this using Java 8 streams. It should work similar to the Scan operator of RxJava.
Example: 5, 2, 2, 5, 13
Threashold: 2
Result: 5, 9, 13
Intermediate results:
5
5, 2
5, 4 (2 and 2 summed)
5, 9 (4 and 5 summed)
5, 9, 13
Sequential Stream solution may look like this:
List<Integer> result = Stream.of(5, 2, 2, 5, 13).collect(ArrayList::new, (list, n) -> {
if(!list.isEmpty() && Math.abs(list.get(list.size()-1)-n) < 2)
list.set(list.size()-1, list.get(list.size()-1)+n);
else
list.add(n);
}, (l1, l2) -> {throw new UnsupportedOperationException();});
System.out.println(result);
Though it looks not much better as good old solution:
List<Integer> input = Arrays.asList(5, 2, 2, 5, 13);
List<Integer> list = new ArrayList<>();
for(Integer n : input) {
if(!list.isEmpty() && Math.abs(list.get(list.size()-1)-n) < 2)
list.set(list.size()-1, list.get(list.size()-1)+n);
else
list.add(n);
}
System.out.println(list);
Seems that your problem is not associative, so it cannot be easily parallelized. For example, if you split the input into two groups like this (5, 2), (2, 5, 13), you cannot say whether the first two items of the second group should be merged until the first group is processed. Thus I cannot specify the proper combiner function.
As Tagir Valeev observed, (+1) the combining function is not associative, so reduce() won't work, and it's not possible to write a combiner function for a Collector. Instead, this combining function needs to be applied left-to-right, with the previous partial result being fed into the next operation. This is called a fold-left operation, and unfortunately Java streams don't have such an operation.
(Should they? Let me know.)
It's possible to sort-of write your own fold-left operation using forEachOrdered while capturing and mutating an object to hold partial state. First, let's extract the combining function into its own method:
// extracted from Tagir Valeev's answer
void combine(List<Integer> list, int n) {
if (!list.isEmpty() && Math.abs(list.get(list.size()-1)-n) < 2)
list.set(list.size()-1, list.get(list.size()-1)+n);
else
list.add(n);
}
Then, create the initial result list and call the combining function from within forEachOrdered:
List<Integer> result = new ArrayList<>();
IntStream.of(5, 2, 2, 5, 13)
.forEachOrdered(n -> combine(result, n));
This gives the desired result of
[5, 9, 13]
In principle this can be done on a parallel stream, but performance will probably degrade to sequential given the semantics of forEachOrdered. Also note that the forEachOrdered operations are performed one at a time, so we needn't worry about thread safety of the data we're mutating.
I know that the Stream's masters "Tagir Valeev" and "Stuart Marks" already pointed out that reduce() will not work because the combining function is not associative, and I'm risking a couple of downvotes here. Anyway:
What about if we force the stream to be sequential? Wouldn't we be able then to use reduce? Isn't the associativity property only needed when using parallelism?
Stream<Integer> s = Stream.of(5, 2, 2, 5, 13);
LinkedList<Integer> result = s.sequential().reduce(new LinkedList<Integer>(),
(list, el) -> {
if (list.isEmpty() || Math.abs(list.getLast() - el) >= 2) {
list.add(el);
} else {
list.set(list.size() - 1, list.getLast() + el);
}
return list;
}, (list1, list2) -> {
//don't really needed, as we are sequential
list1.addAll(list2); return list1;
});
Java 8 way is define custom IntSpliterator class:
static class IntThreasholdSpliterator extends Spliterators.AbstractIntSpliterator {
private PrimitiveIterator.OfInt it;
private int threashold;
private int sum;
public IntThreasholdSpliterator(int threashold, IntStream stream, long est) {
super(est, ORDERED );
this.it = stream.iterator();
this.threashold = threashold;
}
#Override
public boolean tryAdvance(IntConsumer action) {
if(!it.hasNext()){
return false;
}
int next = it.nextInt();
if(next<threashold){
sum += next;
}else {
action.accept(next + sum);
sum = 0;
}
return true;
}
}
public static void main( String[] args )
{
IntThreasholdSpliterator s = new IntThreasholdSpliterator(3, IntStream.of(5, 2, 2, 5, 13), 5);
List<Integer> rs= StreamSupport.intStream(s, false).mapToObj(Integer::valueOf).collect(toList());
System.out.println(rs);
}
Also you can hack it as
List<Integer> list = Arrays.asList(5, 2, 2, 5, 13);
int[] sum = {0};
list = list.stream().filter(s -> {
if(s<=2) sum[0]+=s;
return s>2;
}).map(s -> {
int rs = s + sum[0];
sum[0] = 0;
return rs;
}).collect(toList());
System.out.println(list);
But I am not sure that this hack is good idea for production code.

find out the elements of an arraylist which is not present in another arraylist

I have to find a best way to find out that elements which is not presented in the second arraylist.
suppose
Arraylist a,b,
Arraylist a={1,2,3,4,5};
Arraylist b={2,3,4};
So basically what I want is to find out that elements of a which is not present in arraylist b.
So what is the best solutions to do that?
List<Integer> c = new ArrayList<>(a);
c.removeAll(b);
Also consider to use Sets instead of Lists.
here is another approach using java 8 -
a.stream().filter(b::contains).collect(Collectors.toList());
You could use Apache Commons Collections, which has a method explicitly for this purpose:
public static void main(String[] args) {
List<Integer> a = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
List<Integer> b = Arrays.asList(new Integer[] { 2, 3, 4 });
Collection<Integer> aMinusB = CollectionUtils.subtract(a, b);
System.out.println(aMinusB);
}
The printed result is: [1, 5].
The Apache Commons libs are well tested and commonly used to extend standard Java functionalities. This particular method accepts Iterable as parameters, so you can use any Collection you want. You can also mix different collection types:
public static void main(String[] args) {
List<Integer> a = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
Set<Integer> b = new HashSet<Integer>(Arrays.asList(new Integer[] { 2, 3, 4 }));
Collection<Integer> aMinusB = CollectionUtils.subtract(a, b);
System.out.println(aMinusB);
}
The printed result is the same, [1, 5].
Check out the Javadoc here.
For sake of completeness, Google's Guava library does not have this feature:
Collection *subtract*(Collection, Collection)
No equivalent--create an ArrayList containing a and then call remove on it for each element in b.
However, it implements a method called Sets.difference() method, which you could use if you prefer Guava and work with sets:
public static void main(String[] args) {
Set<Integer> a = new HashSet<Integer>(Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 }));
Set<Integer> b = new HashSet<Integer>(Arrays.asList(new Integer[] { 2, 3, 4 }));
Set<Integer> aMinusB = Sets.difference(a, b);
System.out.println(aMinusB);
}
The result is all elements in a that doesn't exist in b (i.e. [1, 5] again). Of course, the order is not determined since it operates on sets.
You can try removeAll:
List<Integer> notPresent = new ArrayList<Integer>(a);
notPresent.removeAll(b);
Use org.apache.commons.collections4.ListUtils
Given
List<Integer> a = Arrays.asList(new Integer[]{ 1,2,3,4,5});
List<Integer> b = Arrays.asList(new Integer[]{0,1,2,3});
Action
List<Integer> c = ListUtils.removeAll(b, a)
Result in List c
4, 5
Please try like this
for (Object o : a) {
if (!b.contains(o)) {
// this is not present
}
}
Loop through one list, then check if each element in other list using contains.
Something like this. If you think there may be duplicates in a you can try another type of Collection, like a Set for notPresent.
List<Integer> notPresent = new ArrayList<Integer>();
for (Integer n : a){
if (!b.contains(n)){
notPresent.add(n);
}
}
Try this:
public static void main(String[] args) {
List<Integer> a = new ArrayList<Integer>();
List<Integer> b = new ArrayList<Integer>();
List<Integer> exclusion = new ArrayList<Integer>();
a.add(1);
a.add(2);
a.add(3);
a.add(4);
b.add(1);
b.add(2);
b.add(3);
b.add(5);
for (Integer x : a) {
if (!b.contains(x)) {
exclusion.add(x);
}
}
for (Integer x : exclusion) {
System.out.println(x);
}
}
Try this...
Use the contains() method of List.
ArrayList<Integer> aList = new ArrayList<Integer>();
for (Integer i : a){
if (!(b.contains(i))){
aList.add(i);
}
else{
continue;
}
}

Sequential Searching

Ok I am relatively new to Java Programming, but have previous experience in C++. I want to search an array for a specific item, but what if there are more than one of the same specific item? Would it be best to use a temporary array to store all found items in the array and return the temporary array?
Note: I'm trying to find the best way of doing this with memory management and speed. And it's not for Home work:)
Use apache commons lib, which solve a lot of issues. Use this if you want to filter by predicate and select sub array
CollectionUtils.filter(
Arrays.asList(new Integer[] {1,2,3,4,5}),
new Predicate() {
public boolean evaluate(final Object object) {
return ((Integer) object) > 2;
}
}
);
In case if you would like to select item(s) use
CollectionUtils.select(Collection inputCollection, Predicate predicate)
Use true java way - Navigable set and maps
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive);
If you able to skip Java, then in Scala it will be much easier:
scala> val a = Array(4, 6, 8, 9, 4, 2, 4, 2)
a: Array[Int] = Array(4, 6, 8, 9, 4, 2, 4, 2)
scala> a.filter(_ == 4)
res0: Array[Int] = Array(4, 4, 4)
just use guava library as the simplest solution:
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Iterables.html
or
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html
Just use an ArrayList. Example:
/** Returns all strings starting with the letter a.*/
public static List<String> getStartsWithA(String[] strs) {
List<String> ret = new ArrayList<String>();
for (String s: strs) {
if (s.startsWith("a") || s.startsWith("A")) {
ret.add(s);
}
}
return ret;
}
ArrayList's internal array will dynamically grow as more space is needed.
I would use a "ready to use" implementation like a HashMap. You say "search", so I believe that you have a searchkey (in my proposal the String) under wich you can store your data (for example an Integer).
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
void storeValue(final String key, final Integer value) {
List<Integer> l = this.map.get(key);
if (l == null) {
synchronized (this.map) {
if (l == null) {
l = new Vector<Integer>();
this.map.put(key, l);
}
}
}
l.add(value);
}
List<Integer> searchByKey(final String key) {
return this.map.get(key);
}
With this, you can store multiple Integers # one key. Of course you can store other Object than the Integers.

Categories