during the development of ExecutorService, it became necessary to put List in Set . How can this be done?
public class Executor {
private Set<List<Future<Object>>> primeNumList = Collections.synchronizedSet(new TreeSet<>());
Set<List<Future<Object>>> getPrimeNumList() {
return primeNumList;
}
#SuppressWarnings("unchecked")
public void setup(int min, int max, int threadNum) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
List<Callable<Object>> callableList = new ArrayList<>();
for (int i = 0; i < threadNum; i++) {
callableList.add(new AdderImmediately(min + i, max, threadNum));
}
List<Future<Object>> a = executorService.invokeAll(callableList);
primeNumList.add(a); // here i try to add Future list into Set
System.out.println(primeNumList);
executorService.shutdown();
}
My class in which I process the values and return them via call (). After that they fall into the List from where I want them to be placed in the final Set
public class AdderImmediately implements Callable {
private int minRange;
private int maxRange;
private Set<Integer> primeNumberList = new TreeSet<>();
private int step;
AdderImmediately(int minRange, int maxRange, int step) {
this.minRange = minRange;
this.maxRange = maxRange;
this.step = step;
}
#Override
public Object call() {
fillPrimeNumberList(primeNumberList);
return primeNumberList;
}
private void fillPrimeNumberList(Set<Integer> primeNumberList) {
for (int i = minRange; i <= maxRange; i += step) {
if (PrimeChecker.isPrimeNumber(i)) {
primeNumberList.add(i);
}
}
}
}
Is it somehow possible to implement? Because what I have now, I get a ClassCastException. Or am I not understanding something?)
Exception:
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at java.util.Collections$SynchronizedCollection.add(Collections.java:2035)
at Executor.setup(Executor.java:22)
at Demo.main(Demo.java:47)
You are not able to catch the error at compile time because you have used #SuppressWarnings("unchecked"). On removing that, there's a compile warning at this statement: callableList.add(new AdderImmediately(min + i, max, threadNum));
The second problem is, you haven't used generic form while creating AdderImmediately class. You are clearly returning, Set<Integer> type from the call method. If you use the proper generic form in your case, i.e., Callable<Set<Integer>>, the problem becomes clear in the above line. The type of callableList is List<Callable<Object>>. You cannot add an element of type Callable<Set<Integer>> into it.
Because you had added the elements of incorrect type by suppressing generic warnings, you are getting ClassCastException at runtime.
I'd recommend you to read the chapters on Generics from Effective Java 3rd edition to better understand these concepts.
Related
So I have been reviewing my data structures and came across an interesting thought regarding Java generics and the Object class. I have implemented and run a "generic bag" in two different ways (Notice below: IObjectBag.java, ObjectBag.java, IGenericBag.java, and GenericBag.java) and have used them both (Notice: Below main.java and Output). I have removed some of the unnecessary code as per stack overflow rules but if you want the full implementation, let me know.
Also, I have researched the topic in many websites, books and courses in addition to looking at the source code for the ArrayList class here and I understand that my GenericBag is a better option than my ObjectBag but not well enough to explain it in a practical way during an interview. And I am confused that my GenericBag uses more casting operations than my ObjectBag in its implementation (see Remove and PrintBag).
So, other than the syntactic sugar, why is my GenericBag better? Please use my classes as examples.
Are there any important differences in runtime/overhead/space/time I am not noticing?
How would you answer this question or expect it to be answered in an interview?
Bonus questions: If you want, please answer the bonus questions in the Main and GenericBag comments (I think I can answer them myself though, just want to hear your opinion).
IObjectBag interface:
public interface IObjectBag {
void add(Object item);
Object remove(Object item) throws NoSuchElementException;
boolean isEmpty();
int find(Object item);
Object get(int index);
int numItems();
}
ObjectBag class:
public class ObjectBag implements IObjectBag {
private Object [] items; // the java class attribute that will hold out "ints"
private int numItems;
public static void printBag(IObjectBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public ObjectBag(int size) {
this.items = new Object[size]; // fills array with null values
this.numItems = 0;
}
public void add(Object item){
// adds item to end of bag
}
public Object remove(Object item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
Object out = this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// return index given item or -1
}
public Object get(int index) {
// returns item given index
}
}
IGenericBag class:
public interface IGenericBag <T> {
void add(T item);
T remove(T item) throws NoSuchElementException;
boolean isEmpty();
int find(T item);
T get(int index);
}
GenericBag class:
public class GenericBag<T> implements IGenericBag<T> {
// private T[] items; can't use this b/c see comment in constructor
private Object[] items;
private int numItems;
public static void printBag(GenericBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public GenericBag(int size) {
// this.items = new T[size]; Bonus: throws generic array creation error (why?)
this.items = new Object[size];
this.numItems = 0;
}
public void add(T item){
this.items[this.numItems] = item;
this.numItems += 1;
}
public T remove(T item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
T out = (T) this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// given object return index or throw exception
}
public T get(int index) {
return (T) this.items[index];
}
}
Main class:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Hello StackOverFlow!");
Object int1 = new Integer(1);
Object int2 = new Integer(2);
Object int3 = new Integer(3);
/* using my object bag ************************************************/
System.out.println("using my object bag");
IObjectBag myObjectBag = new ObjectBag(3);
myObjectBag.add(int1);
myObjectBag.add(int2);
myObjectBag.add(int3);
myObjectBag.remove(int2);
ObjectBag.printBag(myObjectBag);
/* using my generic bag ***********************************************/
System.out.println("using generic bag");
// Bonus Question: using object like above causes error at add method (why?)
Integer int4 = new Integer(4);
Integer int5 = new Integer(5);
Integer int6 = new Integer(6);
GenericBag<Integer> myGenericBag = new GenericBag<Integer>(3);
//Bonus Question: using Interface decllaration like above causes error in print bag (why?)
myGenericBag.add(int4);
myGenericBag.add(int5);
myGenericBag.add(int6);
myGenericBag.remove(int4);
GenericBag.printBag(myGenericBag);
}
}
Output:
Hello StackOverFlow!
using my object bag
1
3
using generic bag
5
6
Problems with your ObjectBag that are 'automaticaly' solved by the type safety offered by your GenericBag implementation:
Accessing an entry returns Object, at this stage you do not know of what type Object is.
You can insert any types of Objects (mixed) e.g a String and an Integer into the same list, this is an anti pattern and causes non readable code (try it with your Generics bag!)
Because your compiler knows the type of your GenericBag after you have declared it, at any stage of your code if you hover over your genericBag instance you will know its type, this makes your code more readable and also extendable for other people
Generics also offer way more, imagine you want your GenericBag to only accept numbers, then you could write it as follows:
public class GenericBag<T extends Number>
My suggestion for you is to read some articles on Java basics and especially Generics, having a praxis based way of learning is a good thing, but there are plenty articles that can give you some very nice theoretical insight on the matter.
https://www.baeldung.com/java-generics
Reason of using, let's say, GenericBag<String> over ObjectBag is essentially the same as for using String (or any other type) over an Object:
Type safety.
You declare that some method returns a collection of Strings and nothing else, thus preventing yourself from putting there other objects, or trying to treat what you get from a bag as some other type. This might sound stupid when you have 100 lines of code, but this may save you lot of debugging time when you work with decent codebase.
Although, type safety is not a silver bullet, it is just an instrument, that some people find useful and some don't. I'm pretty sure it is a popular holywar topic for any programming forum.
If you feel comfortable working without this paradigm (Javascript background, right?), you might consider trying some dynamically typed language like Python instead of Java.
I'm trying to split a list of objects within smaller sublist and to process them separately on different threads. So I have following code:
List<Instance> instances = xmlInstance.readInstancesFromXml();
List<Future<List<Instance>>> futureList = new ArrayList<>();
int nThreads = 4;
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
final List<List<Instance>> instancesPerThread = split(instances, nThreads);
for (List<Instance> instancesThread : instancesPerThread) {
if (instancesThread.isEmpty()) {
break;
}
Callable<List<Instance>> callable = new MyCallable(instancesThread);
Future<List<Instance>> submit = executor.submit(callable);
futureList.add(submit);
}
instances.clear();
for (Future<List<Instance>> future : futureList) {
try {
final List<Instance> instancesFromFuture = future.get();
instances.addAll(instancesFromFuture);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
And the MyCallable class :
public class MyCallable implements Callable<List<Instance>> {
private List<Instance> instances;
public MyCallable (List<Instance> instances) {
this.instances = Collections.synchronizedList(instances);
}
#Override
public List<Instance> call() throws Exception {
for (Instance instance : instances) {
//process each object and changing some fields;
}
return instances;
}
}
Split method(It's split an given list in given number of list, also trying to have almost same size on each sublist) :
public static List<List<Instance>> split(List<Instance> list, int nrOfThreads) {
List<List<Instance>> parts = new ArrayList<>();
final int nrOfItems = list.size();
int minItemsPerThread = nrOfItems / nrOfThreads;
int maxItemsPerThread = minItemsPerThread + 1;
int threadsWithMaxItems = nrOfItems - nrOfThreads * minItemsPerThread;
int start = 0;
for (int i = 0; i < nrOfThreads; i++) {
int itemsCount = (i < threadsWithMaxItems ? maxItemsPerThread : minItemsPerThread);
int end = start + itemsCount;
parts.add(list.subList(start, end));
start = end;
}
return parts;
}
So, when I'm trying to execute it, I'm getting java.util.ConcurrentModificationException on this line for (Instance instance : instances) {, can somebody give any ideas why it's happening?
public MyCallable (List<Instance> instances) {
this.instances = Collections.synchronizedList(instances);
}
Using synchronizedList like this doesn't help you in the way you think it might.
It's only useful to wrap a list in a synchronizedList at the time you create it (e.g. Collections.synchronizedList(new ArrayList<>()). Otherwise, the underlying list is directly accessible, and thus accessible in an unsynchronized way.
Additionally, synchronizedList only synchronizes for the duration of individual method calls, not for the whole time while you are iterating over it.
The easiest fix here is to take a copy of the list in the constructor:
this.instances = new ArrayList<>(instances);
Then, nobody else has access to that list, so they can't change it while you are iterating it.
This is different to taking a copy of the list in the call method, because the copy is done in a single-threaded part of the code: no other thread can be modifying it while you are taking that copy, so you won't get the ConcurrentModificationException (you can get a CME in single-threaded code, but not using this copy constructor). Doing the copy in the call method means the list is iterated, in exactly the same way as with the for loop you already have.
Just to start off, I'm pretty inept at Java and especially multithreading, so what I'm asking might sound a bit ordinary. I am attempting to create a program in which I create three threads which each accomplish the specific task of depicting certain values between ten integers, such as average, deviation, etc. How would I approach this?
I am attempting to create four classes, one for the main program, and three for each of the calculations of the values between each: class "Average" for the average of the ten numbers in the array, class "Median" for the median, etc. The code for the other 3 classes I can easily write, no problem there. My main problem is that since the list "integers" is not available outside the class, I can't write the code for finding each of the values I need in the three programs.
Is there a better way to write this so I can actually access the list from inside the classes for each of the threads?
import java.util.*;
public class ThreadDemo
{
public static void main(String[] args)
{
Random number = new Random();
List integers = new ArrayList();
for (int i = 0; i < 10; i++)
{
integers.add(number.nextInt(101));
}
Thread average = new Thread(new Average());
Thread median = new Thread(new Median());
Thread deviation = new Thread(new Deviation());
average.start();
median.start();
deviation.start();
}
}
class Average extends Thread
{
public void run()
{
// code for finding average
}
}
class Median extends Thread
{
public void run()
{
// code for finding median
}
}
class Deviation extends Thread
{
public void run()
{
// code for finding deviation
}
}
There are a lot of options to achieve what you are trying to do. I will outline two:
each computation method implementing the Callable interface and taking data into the instance constructor;
each computation method implementing the Function interface and passing data into the call via the closure.
It is generally advisable to program to interfaces, that is require an interface as method argument. All below examples follow this by implementing Callable or Function and working with those high level interfaces elsewhere. The code for both cases looks very similar with the main difference being the remapping of Function to Callable in the latter case using the closure state.
Let's start with some common utilities (statics for brevity only):
The following method will create a Collection of 100 random integers in [0,100]:
private static Collection<Integer> ints() {
Random random = new Random();
return random.ints(100, 0, 100)
.boxed()
.collect(Collectors.toList());
}
The following method will execute a collection of Callables concurrently on a cached executor pool. Each callable is generic and will deliver a double value. Those values (in random order) will be collected and returned as a list:
private static List<Double> concurrently(Collection<Callable<Double>> callables) throws InterruptedException, ExecutionException {
ExecutorService executors = Executors.newCachedThreadPool();
Collection<Future<Double>> futures = executors.invokeAll(callables);
List<Double> res = new ArrayList<>();
for (Future<Double> future: futures) {
res.add(future.get());
}
executors.shutdownNow();
return res;
}
Now let's get back to the core logic.
Case 1: Implementing Callable
class Averager<V extends Number> implements Callable<Double> {
private final Collection<V> values = new ArrayList<>();
Averager(Collection<V> values) {
this.values.addAll(values);
}
#Override
public Double call() {
double sum = 0.0;
for (V value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
}
}
class Medianer<V extends Number> implements Callable<Double> {
private final Collection<V> values = new ArrayList<>();
Medianer(Collection<V> values) {
this.values.addAll(values);
}
#Override
public Double call() {
List<V> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
}
}
Note: whenever you take a collection as a constructor argument, do not store the reference to the original collection provided in a private field, copy values. If collections are very large, do not pass them to constructor or make unmodifiable.
#Test
public void usingCallable() throws InterruptedException, ExecutionException {
Collection<Integer> values = ints();
Collection<Callable<Double>> callables = new ArrayList<>();
callables.add(new Averager<>(values));
callables.add(new Medianer<>(values));
List<Double> res = concurrently(callables);
System.out.println(res);
}
Case 2: Implementing Function
class Averager<V extends Number> implements Function<Collection<V>, Double> {
#Override
public Double apply(Collection<V> values) {
double sum = 0.0;
for (V value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
}
}
class Medianer<V extends Number> implements Function<Collection<V>, Double> {
#Override
public Double apply(Collection<V> values) {
List<V> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
}
}
#Test
public void usingFunction() throws InterruptedException, ExecutionException {
Collection<Integer> values = ints();
Collection<Function<Collection<Integer>, Double>> functions = new ArrayList<>();
functions.add(new Averager<>());
functions.add(new Medianer<>());
List<Callable<Double>> callables = functions.stream().map(f -> (Callable<Double>) () -> f.apply(values)).collect(Collectors.toList());
List<Double> res = concurrently(callables);
System.out.println(res);
}
I personally prefer the latter one because your computation methods become generic functions, that is implementing the generic Function interface and can be used in other contexts.
Reworking case 1 and 2 with lambdas
You can do some interesting things with lambdas here. For the case of functions, you can just predefine them as lambdas instead of constructing new instances of specifically defined class:
static final Function<Collection<Integer>, Double> averager = (values) -> {
double sum = 0.0;
for (Integer value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
};
static final Function<Collection<Integer>, Double> medianer = (values) -> {
List<Integer> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
};
Followed later by:
Collection<Function<Collection<Integer>, Double>> functions = new ArrayList<>();
functions.add(averager);
functions.add(medianer);
For the case of callable you can nicely inline them:
Collection<Callable<Double>> callables = new ArrayList<>();
callables.add(() -> {
double sum = 0.0;
for (Integer value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
});
callables.add(() -> {
List<Integer> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
});
Note how you do not need external declarations in the latter case.
Note: as you do not want your results in a random order you will need you function return a pair, e.g. Map.Entry, with a key and a value. But I will leave that to you to exercise.
A sample execution for one of those methods would print something like
[53.01,57.0]
You can pass as a constructor argument. Also, after starting the threads, you must call join, otherwise the main thread will not wait the others to finish:
average.start();
median.start();
deviation.start();
average.join();
median.join();
deviation.join();
```
I have a method which uses Deque. In 1 place, sometimes I want to Deque.pullFirst() and sometimes Deque.pullLast(). It should depend on one of the arguments passed to the method. How do this with Java 8?
This is my try with Callable I know that it doesn't work but now you can understand what I want to achieve:
public class AppMain {
public void iterateThroughQueue(Callable callable) { // error
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(callable.apply(deq)); // error!
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
AppMain.iterateThroughQueue(Deque::pollFirst); // error!
}
}
Method references are either:
Consumer<T>, which means they take a parameter and return nothing. For example System.out::println is a Consumer<String>.
Producer<T>, which means they take no parameter and return something. For example UUID::randomUUID is a Producer<UUID>.
Function<T,Z>, which means they take a parameter of type T (can be the instance on which to apply the method) and return a result of type Z, in your case Deque::pollFirst take is a Function<Deque<Integer>, Integer>. Another example is deq::add where deq is an instance of Deque<Integer> which would be a Function<Integer, Boolean> .
So you should be using Function<Deque<Integer>, Integer> instead of Callable which is for something completely different. Also iterateThroughQueue(...) need to be static.
Callable will not work here, but Function will.
You could try instead this:
public static void iterateThroughQueue(Function<Deque<Integer>, Integer> function) {
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(function.apply(deq));
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
iterateThroughQueue(Deque::pollFirst);
}
This prints:
1
2
3
size after iteration = 0
I'm not sure why this doesn't work in Java:
import java.util.Map;
public class FreqCounter<T,R> {
private Map<T, Integer> hist;
private R item;
public FreqCounter (final R item_) {
item = item_;
}
public T getMostFrequentElement() {
T most_frequent_element = T();
Integer highestcount = 0;
for(T t : item) {
Integer count = hist.get(t);
if(count == null) {
hist.put(t, 1);
}
else {
hist.put(t, count + 1);
}
if(count + 1 > highestcount) {
most_frequent_element = t;
highestcount = count + 1;
}
}
return most_frequent_element;
}
}
class HelloWorld {
public static void main(String[] args) {
String s = "aaabbcccc";
FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
}
}
Problem lines:
1. T most_frequent_element = T();
2. for(T t : item)
3. FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
Cannot find symbol: method T()
required: array or java.lang.Iterable, found: R
Required java.lang.Integer
Found: java.lang.String
reason: actual argument java.lang.String cannot be converted to java.lang.Integer by method invocation conversion
What I was trying to do was make a class that could count how many times an element in an iterable container shows up. Originally I just wanted to make it to count characters in a string but I thought I could make it more general. I think some of this would work in C++?
Also, does FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s); need to be "newed" as opposed to declared on the stack?
T is a Generic type, not a real one, and one of the limitations of generics is that you cannot instantiate a new one (which is what I think you were trying to do here).
What you can do though is assign, call methods in, keep references too, duplicate references too, etc.
What you probably actually wanted to do was pull the set of Ts out of the keySet of the Map.
T t = null;
int count = 0;
for (Entry<T, Integer> e: hist.entrySet()) {
if (e.getValue() > count) {
count = e.getValue();
t = e.getKey();
}
}
return t;
Java Generics provide a lot of the same functionality that C++ templates do, but they work in quite a different way. Quite apart from anything else you only have one ArrayList class no matter how many different ways you instantiate one. The generics are used for compiler time type checking and then erased and are not present at all during run time.