I wrote a Predicate code that takes any Object and tests it for the following conditions:
if Object type is String and contains "k" then it should return true.
if Object type is Integer and greater than 100 then it should return true.
if Object type is Employee which is class and having salary of employee greater than 60000, it should return true.
After writing that Predicate method I wrote the remove method that removes values from list according to Predicate method.
public class ConditionalRemove {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
System.out.println(conditionalRemove(list));
}
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
ConditionCheck<T> cond = new ConditionCheck<>();
for (T t : list) {
if (cond.test(t)) {
list.remove(t);
}
}
return list;
}
static class ConditionCheck<T> implements Predicate<T> {
#Override
public boolean test(T t) {
if (t instanceof String) {
return (((String) t).contains("k"));
} else if (t instanceof Integer) {
return ((int) t > 100);
} else if (t instanceof Employee) {
return ((int) ((Employee) t).getSalary() < 60000);
}
return true;
}
}
}
After compiling this code I found Exception in thread "main" java.util.ConcurrentModificationException
The issue is you are updating the list when you are iterating over that. The issue can be fixed by updating code as
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
ConditionCheck<T> cond = new ConditionCheck<>();
Iterator it = list.iterator();
while(it.hasNext())
{
it.next();
if (cond.test(t)) {
it.remove();
}
}
return list;
}
Since you're using Java 8, a functional approach would be to create a new filtered list:
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
return list.stream()
.filter(new ConditionCheck<>())
.collect(Collectors.toList());
}
You can even replace the static inner class by just a method:
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
return list.stream()
.filter(ConditionalRemove::test)
.collect(Collectors.toList());
}
private static <T> boolean test(T t) {
// your predicate implementation...
}
Don't reinvent the wheel: Use Collection#removeIf():
public static <T> List<T> conditionalRemove(ArrayList<T> list) {
list.removeIf(new ConditionCheck<>());
return list;
}
At one line, this is hardly worth the effort of creating a method to call... just make the single line call in-line:
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
list.removeIf(new ConditionCheck<>());
System.out.println(list);
}
Some data structures throws the java.util.ConcurrentModificationException when you modify them during an iteration, in order to do that with success you need use a synchronized structure such as "CopyOnWriteArrayList", this is the java doc reference
Hope this can help you!
Regards.
Related
Problem : I have a utility function which takes in a generic list to remove duplicates, Now when I use it for List<String> the match should case insensitive. The code uses streams (Java 8+) and i want to keep it that way.
Note : code is in JAVA 8+
Code :
public static <T> List<T> removeDuplicates(List<T> inputList) {
List<T> result = null;
if (inputList != null && inputList.size() > 0) {
result = inputList.parallelStream().distinct().collect(Collectors.toList());
}
return result;
}
EG:
List<String> inputList = new ArrayList<String>();
inputList.add("a");
inputList.add("A");
inputList.add("abc");
inputList.add("ABC");
inputList.add("c");
When we call removeDuplicates(inputList) and print it
Values:
a
abc
c
I don't really care if it choose ABC over abc or A over a but it should be there only once.
Is there an elegant way of solving this issue without doing an instanceof check ?
If the caller knows the type of T at compile time, you can have it pass an optional Comparator<T> to the method, and filter out duplicates using a TreeSet:
public static <T> List<T> removeDuplicates(List<T> inputList) {
// null uses natural ordering
return removeDuplicates(inputList, null);
}
public static <T> List<T> removeDuplicates(List<T> inputList, Comparator<? super T> comparator) {
Set<T> set = new TreeSet<>(comparator);
set.addAll(inputList);
return new ArrayList<>(set);
}
public static void main(String[] args) {
System.out.println(removeDuplicates(Arrays.asList(1, 2, 2, 3)));
System.out.println(removeDuplicates(Arrays.asList("a", "b", "B", "c"), String.CASE_INSENSITIVE_ORDER));
}
Output:
[1, 2, 3]
[a, b, c]
You can extend your method to accept also a function to be applied in map on your stream.
This function will be generic with the same T, so this will solve the need for instanceof. In the String case insensitive example, the function will be String::toLowerCase.
public static <T> List<T> removeDuplicates(List<T> inputList, Function<T,T> function) {
List<T> result = null;
if (inputList != null && inputList.size() > 0) {
result = inputList.parallelStream()
.map(function)
.distinct()
.collect(Collectors.toList());
}
return result;
}
And if you want to keep the same API for the types that don't need it, just add this overload:
public static <T> List<T> removeDuplicates(List<T> inputList) {
return removeDuplicates(inputList, Function.identity());
}
If you want behavior that differs from the default equals behavior you can roll your own String:
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.stream.Collectors;
public class MyString {
private final String value;
public MyString(final String value) {
this.value = value;
}
#Override
public String toString() {
return value;
}
public String getValue() {
return value;
}
#Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final MyString myString = (MyString) o;
return StringUtils.equalsIgnoreCase(myString.value, value);
}
#Override
public int hashCode() {
return value.toUpperCase().hashCode();
}
public static void main(String... args) {
// args = {aa AA aA bb Bb cc bb CC}
System.out.println(Arrays.stream(args).map(MyString::new).collect(Collectors.toSet()));
// prints: [aa, bb, cc]
}
}
For a homework assignment, I need to implement my own PriorityQueue and PriorityQueueSort. I used generics to get it working without the sort function, but now I'm stuck here..
public static void PriorityQueueSort(Iterable<?> list,
PriorityQueue<?,?> pq) {
if (!pq.isEmpty()) {
throw new IllegalArgumentException("Non-Empty PriorityQueue");
}
for (Object obj : list) {
}
}
I need to pass in a list and an empty PriorityQueue, so my best guess at how to do this is just above. How should I attack this so that I can iterate through the list with unknown type, and add each element in that list with the proper type into the priority queue?
Edit:
Here are a few more details since it was determined that I didn't include enough information.
I have a custom PriorityQueue class, and a custom Entry class that holds a key of type K, and a value of type V.
I need to be able to take any iterable list with any type T and iterate through it, taking each item and add it to an initially empty PriorityQueue as a key with null value. I then need to continuously call removeMin() on my PriorityQueue and add it in order back into the same list object.
public class PriorityQueue<K extends Comparable<? super K>,V> {
private Entry<K,V> _head;
private Entry<K,V> _tail;
private int _size;
public PriorityQueue() {
this._head = null;
this._tail = null;
this._size = 0;
}
public int size() {
return _size;
}
public boolean isEmpty() {
return (size() == 0);
}
public Entry<K,V> min() {
if (_head == null) {
return null;
}
Entry<K,V> current = _head;
Entry<K,V> min = _head;;
while (current != null) {
if (current.compareTo(min) < 0) {
min = current;
}
current = current.getNext();
}
return min;
}
public Entry<K,V> insert(K k, V x) {
Entry<K,V> temp = new Entry<K,V>(k,x);
if (_tail == null) {
_tail = temp;
_head = temp;
}
else {
_tail.setNext(temp);
temp.setPrev(_tail);
_tail = temp;
}
return temp;
}
public Entry<K,V> removeMin() {
Entry<K,V> smallest = min();
smallest.getPrev().setNext(smallest.getNext());
smallest.getNext().setPrev(smallest.getPrev());
return smallest;
}
public String toString() {
return null;
}
public static <K> void PriorityQueueSort(Iterable<? extends K> list,
PriorityQueue<? super K, ?> queue) {
for (K item : list) {
queue.insert(item, null);
}
list.clear();
}
public static void main(String[] args) {
PriorityQueue<Integer, Integer> pq =
new PriorityQueue<Integer, Integer>();
pq.insert(4, 2);
pq.insert(5, 1);
System.out.println(pq.min().toString());
}
}
What you've got at the moment doesn't make sense in terms of the method signature - it would let you pass in a List<Button> and a PriorityQueue<String> for example.
I suspect you actually want something like:
public static <T> void prioritySortQueue(Iterable<? extends T> iterable,
PriorityQueue<? super T> queue) {
for (T item : iterable) {
queue.add(item);
}
}
Note that the variance here just gives more flexibility - you could have a List<Circle> but a PriorityQueue<Shape> for example, and it's still type-safe.
EDIT: Now that we have more details, I think you want something like this:
public static <K> void prioritySortQueue(Iterable<? extends K> iterable,
PriorityQueue<? super K, ?> queue) {
for (T item : iterable) {
queue.put(item, null);
}
}
(Assuming you have a put method. We still don't know what your PriorityQueue class looks like.)
You need to make the method generic so that you can refer to the type:
public static <T> void PriorityQueueSort(Iterable<T> list,
PriorityQueue<?,T> pq) {
I Need a java function which converts from java.util.List to java.util.Set and vice versa, independent of type of objects in the List/Set.
Like List.addAll and Set.addAll?
Most of the class of the java collection framework have a constructor that take a collection of element as a parameter. You should use your prefered implementation ton do the conversion for exameple (with HashSet and ArrayList):
public class MyCollecUtils {
public static <E> Set<E> toSet(List<E> l) {
return new HashSet<E>(l);
}
public static <E> List<E> toSet(Set<E> s) {
return new ArrayList<E>(s);
}
}
public static <E> Set<E> getSetForList(List<E> lst){
return new HashSet<E>(lst);//assuming you don't care for duplicate entry scenario :)
}
public static <E> List<E> getListForSet(Set<E> set){
return new ArrayList<E>(set);// You can select any implementation of List depending on your scenario
}
Instead of one function you can have two function to implement this functionality:
// Set to List
public List setToList(Set set) {
return new ArrayList(set);
}
// List to Set
public Set listToSet(List list) {
return new HashSet(list);
}
In a single function:
public Collection convertSetList(Collection obj) {
if (obj instanceof java.util.List) {
return new HashSet((List)obj);
} else if(obj instanceof java.util.Set) {
return new ArrayList((Set)obj);
}
return null;
}
Example: (updated)
public class Main {
public static void main(String[] args) {
Set s = new HashSet();
List l = new ArrayList();
s.add("1");s.add("2");s.add("3");
l.add("a");l.add("b");l.add("c");
Collection c1 = convertSetList(s);
Collection c2 = convertSetList(l);
System.out.println("c1 type is : "+ c1.getClass());
System.out.println("c2 type is : "+ c2.getClass());
}
public static Collection convertSetList(Collection obj) {
if (obj instanceof java.util.List) {
System.out.println("List!");
return (Set)new HashSet((List) obj);
} else if (obj instanceof java.util.Set) {
System.out.println("Set!");
return (List)new ArrayList((Set) obj);
} else {
System.out.println("Unknow type!");
return null;
}
}
}
So I have this code. Basically it should be able to take a stock of any type, and you should be able to buy from this stock into a collection of any type, including Objects.
For the main function i have this. Basically i have an stock inventory of strings, and I want to buy form this stock inventory of strings into a set of objects. However, I get this error.
add(capture#880 of ?) in java.util.Collection cannot be applied to (T)
import java.util.*;
public class lab6 {
public static void main(String[] args) {
Shop<String> turkey= new Shop<String>();
turkey.sell("pork");
turkey.sell("chicken");
turkey.print();
Set<Object> possessions= new HashSet<Object>();
turkey.buy(2,possessions);
for(String e:possessions)
System.out.println(e);
}
}
Then this is the class file.
import java.util.*;
public class Shop<T> {
List<T> stock;
public Shop() { stock = new LinkedList<T>(); }
public T buy() {
return stock.remove(0);
}
void sell(T item) {
stock.add(item);
}
void buy(int n, Collection<?> items) {
for (T e : stock.subList(0, n)) {
items.add(e);
}
for (int i=0; i<n; ++i) stock.remove(0);
}
}
Replace your buy method with this:
void buy(int n, Collection<T> items) {
for (T e : stock.subList(0, n)) {
items.add(e);
}
for (int i=0; i<n; ++i) stock.remove(0);
}
You were using Collection<?>
EDIT:
Also change your main to this:
public static void main(final String[] args) {
final Shop<String> turkey = new Shop<String>();
turkey.sell("pork");
turkey.sell("chicken");
turkey.print();
final Set<String> possessions = new HashSet<String>();
turkey.buy(2, possessions);
for (final String e : possessions) {
System.out.println(e);
}
}
and write a print() method in Shop.
The problem here is that Collection<?> can contain any type of object, and T may not be a subtype of the ? type. For example, you could pass in a Collection<Integer> and if T is String, clearly you can't do items.add(e).
You need to make sure that the Collection holds a supertype of T so that it is always valid to add a T, so try something like:
void buy(int n, Collection<? super T> items)
The question but in C#. So does Java have C#'s command? I need it for Matches-SearchTerm-Files-relationship.
foreach(var i in BunchOfItems.SelectMany(k => k.Items)) {}
[Why not for-loops?]
I have done such structures in nested for loops but they soon become bloated. So I prefer something more succint like the above.
public static Stack<Integer[]> getPrintPoss(String s,File f,Integer maxViewPerF)
{
Stack<File> possPrint = new Stack<File>();
Integer[] poss = new Integer[4]();
int u,size;
for(File f:files)
{
size = f2S(f).length();
u = Math.min(maxViewsPerF,size);
for(int i=0; i<u;i++)
{
// Do something --- bloated, and soon out of control
// wants more succintly
}
}
return possPrint;
}
for (List<Object> lo : list) {
for (Object o : lo) {
// etc etc
}
}
I don't think there's a simpler solution.
If you can get the data into an Iterable<Iterable<T>>, then you can get from that to a flattened Iterable<T> using Guava's Iterables.concat method. If what you have is really an Iterable<S>, with some way to get from an S to an Iterable<T>, well, then you have to first use Iterables.transform to view that as the Iterable<Iterable<T>> needed by concat.
All this will look a lot nicer if and when Java has something resembling closures, but at least today it's possible.
http://guava-libraries.googlecode.com
With Java 8, you can say
Collection bunchOfItems = ...;
bunchOfItems.stream().flatMap(k::getItems).forEach(i -> /* operate on i */);
or
Item[] bunchOfItems = ...;
Stream.of(bunchOfItems).flatMap(k::getItems).forEach(i -> /* operate on i */);
depending upon whether you have a Collection or an Array.
Have about half a year patience until JDK7 is final which will include Closures. This provides simliar syntax and the same possibilities as LINQ which was demonstrated in the answer you're talking about.
I have my own version. Waiting desperately for Closures in Java :
public static <T, E> Iterable<T> transformMany(Iterable<E> iterable, Func<E, Iterable<T>> f) {
if (null == iterable)
throw new IllegalArgumentException("null iterable");
if (null == f)
throw new IllegalArgumentException("null f");
return new TransformManyIterable<E, T>(iterable, f);
}
public interface Func<E, T> {
T execute(E e);
}
public class TransformManyIterable<TOriginal, TResult> implements Iterable<TResult> {
private Iterable<TOriginal> iterable;
private Func<TOriginal, Iterable<TResult>> func;
public TransformManyIterable(Iterable<TOriginal> iterable,
Func<TOriginal, Iterable<TResult>> func) {
super();
this.iterable = iterable;
this.func = func;
}
class TransformIterator implements Iterator<TResult> {
private Iterator<TOriginal> iterator;
private Iterator<TResult> currentIterator;
public TransformIterator() {
iterator = iterable.iterator();
}
#Override
public boolean hasNext() {
if (currentIterator != null && currentIterator.hasNext())
return true;
else {
while (iterator.hasNext()) {
Iterable<TResult> iterable = func.execute(iterator.next());
if (iterable == null)
continue;
currentIterator = iterable.iterator();
if (currentIterator.hasNext())
return true;
}
}
return false;
}
#Override
public TResult next() {
if (currentIterator != null && currentIterator.hasNext())
return currentIterator.next();
else {
while (iterator.hasNext()) {
Iterable<TResult> iterable = func.execute(iterator.next());
if (iterable == null)
continue;
currentIterator = iterable.iterator();
if (currentIterator.hasNext())
return currentIterator.next();
}
}
throw new NoSuchElementException();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
#Override
public Iterator<TResult> iterator() {
return new TransformIterator();
}
}
Usage:
Iterable<SomeType> result = transformMany(input, new Func<InputType, Iterable<SomeType>>() {
#Override
public Iterable<SomeType> execute(InputType e) {
return new ArrayList<SomeType>();
}
});
The SelectMany method is part of LINQ which is .Net-specific. This question asks about a LINQ equilvalent for java. Unfortunately, it doesn't look like there is a direct equivalent.