What I am trying to achieve is a map of generic lists that I can then serialize. I have achieved this but probably not in the best way, anyway I don't understand one point which I describe further below.
Basically I don't see how mClass ends up being "[Ljava.lang.Integer" i.e. Integer[] and not only "java.lang.Integer".
Edit: In order to make my question clear. I don't understand why mClass is Integer[] when I instantiated the class with GenericArrayData< Integer>, i.e. I was expecting Integer. Thanks
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import junit.framework.Assert;
import org.junit.Test;
public class TestDataCollectorTest {
public class GenericArrayData<T> {
public Class mClass;
public CopyOnWriteArrayList<T[]> data;
public GenericArrayData(Class<T> type) {
mClass = type;
data = new CopyOnWriteArrayList<>();
}
}
public <T> void logGenericArrayData(HashMap<String, GenericArrayData> map, String tag, T[] obj) {
if (map.containsKey(tag)) {
GenericArrayData<T> d = map.get(tag);
d.data.add(obj);
return;
}
System.out.println("Adding log entry named\"" + tag + "\"");
Class k = obj.getClass();
GenericArrayData<T> d = new GenericArrayData<T>(k);
d.data.add(obj);
map.put(tag, d);
}
#Test
public void basics() {
HashMap<String, GenericArrayData> map = new HashMap<>();
GenericArrayData<Integer> list = new GenericArrayData<>(Integer.class);
Integer[][] inputData = new Integer[10][10];
for (int i = 0; i < inputData.length; ++i) {
inputData[i] = new Integer[10];
for (int j = 0; j < inputData[0].length; ++j) {
inputData[i][j] = i * 100 + j;
}
logGenericArrayData(map, "integers", inputData[i]);
}
Assert.assertEquals(1, map.size());
GenericArrayData d = map.get("integers");
Assert.assertEquals(10, d.data.size());
System.out.println(d.mClass);
Integer[] ia = new Integer[0];
System.out.println(ia.getClass());
Assert.assertTrue(ia.getClass() == d.mClass); // I don't quite understand
Integer[][] outputData = new Integer[d.data.size()][];
outputData = (Integer[][]) d.data.toArray(outputData);
Assert.assertEquals(inputData.length, outputData.length);
for (int i = 0; i < inputData.length; ++i) {
Assert.assertEquals(inputData[i], outputData[i]);
}
}
}
Related
Write a Java client-server program applying RMI. The client program generate two arrays of type class Integer. The client calls method that is on the server side in a remote object. The server put these two arrays into one array, sort the array and returns the sorted array to the client. The client displays the sorted array on the console. Use the following interface. Do not change it.
import java.util.ArrayList;
import java.rmi.*;
public interface MergeInterface extends Remote {
public ArrayList mergeAndSort(ArrayList a, ArrayList b) throws RemoteException;
}
The following sequential program is putting two arrays together, sorting array and display:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> a = new ArrayList<Integer>();
ArrayList<Integer> b = new ArrayList<Integer>();
Random r = new Random();
int m = r.nextInt(900) + 100;
for (int i = 0; i < m; i++) {
a.add(r.nextInt(500) + 10);
}
int n = r.nextInt(900) + 100;
for (int i = 0; i < n; i++) {
b.add(r.nextInt(500) + 10);
}
a.addAll(b);
Collections.sort(a);
for (Integer i : a) {
System.out.println(i);
}
}
}
This is how to implement an interface on a class. I would also consider creating a generic class for this or strongly typing the ArrayLists, but that requires a change to the interface.
public interface MergeInterface extends Remote {
public ArrayList mergeAndSort(ArrayList a, ArrayList b) throws RemoteException;
}
public static void main(String[] args) {
ArrayList a = new ArrayList();
ArrayList b = new ArrayList();
Random r = new Random();
int m = r.nextInt(900) + 100;
for (int i = 0; i < m; i++) {
a.add(r.nextInt(500) + 10);
}
int n = r.nextInt(900) + 100;
for (int i = 0; i < n; i++) {
b.add(r.nextInt(500) + 10);
}
for (Integer i : (ArrayList<Integer>)new MergeImpl().mergeAndSort(a, b)) {
System.out.println(i);
}
}
public static class MergeImpl implements MergeInterface {
#Override
public ArrayList mergeAndSort(ArrayList a,
ArrayList b) {
ArrayList merged = new ArrayList();
merged.addAll(a);
merged.addAll(b);
Collections.sort(merged);
return merged;
}
}
I am having a problem with this consumer class.
When i run the program i get an out of bounds exception with each thread in the pool.
I have sysout the list size and it is zero for some reason.
Please see my code below.
I'ts something to with the list being set but i cant figure it out.
Every other part of the program is working and tested just this last part is giving me problems.
Any help offered would be greatly appreciated.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Consumer implements Runnable {
private BlockingQueue<Shingle> q;
private int k;
private int[] minHashes;
private Map<Integer, List<Integer>> map = new HashMap<>();
private ExecutorService pool;
public Consumer(BlockingQueue<Shingle> q, int k, int poolSize) {
super();
this.q = q;
this.k = k;
pool = Executors.newFixedThreadPool(poolSize);
init();
}
public void init() {
Random random = new Random();
minHashes = new int[k];
for (int i = 0; i < minHashes.length; i++) {
minHashes[i] = random.nextInt();
}
}
public void run(){
try {
int docCount = 2;
while (docCount > 0) {
Shingle s = q.take();
if (s instanceof Poision) {
docCount--;
} else {
pool.execute( new Runnable() {
public void run() {
for (int i = 0; i < minHashes.length; i++) {
int value = s.getHashCode() ^ minHashes[i]; // ^ - xor(Random generated key)
List<Integer> list = map.get(s.getDocId());
if (list == null) {
list = new ArrayList<Integer>(k);
for (int j = 0; j < list.size(); j++) {
list.set(j , Integer.MAX_VALUE);
}
map.put(s.getDocId(), list);
} else {
if (list.get(i) > value) {
list.set(i, value);
}
}
}
}
});
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The issue is that this line
list = new ArrayList<Integer>(k);
create list with initial capacity equal to k not with size equal to k. So your list has 0 elements and the for loop
for (int j = 0; j < list.size(); j++) {
list.set(j , Integer.MAX_VALUE);
}
doesn't execute any iteration. You then add empty list to the map and because of that list.get(i) throws exception.
Please change your for loop to
for (int j = 0; j < minHashes.length; j++) {
list.add(Integer.MAX_VALUE);
}
to actually add elements to list.
I have an ArrayList filled with objects of the class result, each result has an attribute named value. I now want to create an Array which is filled with references to the same memory location as in the ArrayList but now in order where to object with the highest value is in the first location, the second highest in the second location and so forth.
I have searched here but haven't found any other post like it.
There are multiple ways to solve it using Gauava or lambda expressions.
Hope this implementation solve your problem.
package com;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestDemo {
public static void main(String[] args) {
List < HockeyPlayer > players = new ArrayList < HockeyPlayer > ();
HockeyPlayer obj1 = new HockeyPlayer();
obj1.goalsScored = 22;
players.add(obj1);
HockeyPlayer obj2 = new HockeyPlayer();
obj2.goalsScored = 11;
players.add(obj2);
HockeyPlayer obj3 = new HockeyPlayer();
obj3.goalsScored = 111;
players.add(obj3);
HockeyPlayer obj4 = new HockeyPlayer();
obj4.goalsScored = 3;
players.add(obj4);
Collections.sort(players, new Comparator < HockeyPlayer > () {
#Override public int compare(HockeyPlayer player1, HockeyPlayer player2) {
return player1.goalsScored - player2.goalsScored;
}
});
for (int i = 0; i < players.size(); i++) {
System.out.println(players.get(i).goalsScored);
}
HockeyPlayer array[] = new HockeyPlayer[players.size()];
players.toArray(array); // contains reference
for (int i = 0; i < array.length; i++) {
System.out.println(array[i].goalsScored);
}
}
}
class HockeyPlayer {
public int goalsScored;
}
I have two ArrayLists, teamList1 and teamList2, which each contain five Team objects. I'm comparing those contents to each other in one of my methods. I must pass in these two ArrayLists as a single 2-element simple array argument, Objects[], into the method. I'm getting a compiler error because I'm struggling with casting from type Objects into type Team. In other words, changing from a Collection to a simple array back to a Collection is giving me an error. Anyone have a tip on my casting error?
CommonElements.java
package test;
import javax.swing.*;
import java.util.*;
public class CommonElements {
List<Comparable> teamList1 = new ArrayList<Comparable>();
List<Comparable> teamList2 = new ArrayList<Comparable>();
List<Comparable> commonList = new ArrayList<Comparable>();
Object[] listCollection = new Object[2];
int comparisonCount;
public static void main(String[] args) {
new CommonElements();
}
public CommonElements() {
comparisonCount = 0;
Team a = new Team("Boston");
Team b = new Team("Seattle");
Team c = new Team("Newark");
Team d = new Team("Houston");
Team e = new Team("Salt Lske City");
teamList1.add(a);
teamList1.add(b);
teamList1.add(c);
teamList1.add(d);
teamList1.add(e);
Team f = new Team("Seattle");
Team g = new Team("Nashville");
Team h = new Team("St. Louis");
Team i = new Team("New York");
Team j = new Team("Boston");
teamList2.add(f);
teamList2.add(g);
teamList2.add(h);
teamList2.add(i);
teamList2.add(j);
listCollection[0] = teamList1;
listCollection[1] = teamList2;
findCommonElements(listCollection);
System.out.println(comparisonCount);
}
public Comparable[] findCommonElements(Object[] collections)
{
ArrayList<Object> objectTeam1 = new ArrayList<Object>(Arrays.asList(collections[0]));
ArrayList<Object> objectTeam2 = new ArrayList<Object>(Arrays.asList(collections[1]));
ArrayList<Team> team1 = (ArrayList)objectTeam1;
ArrayList<Team> team2 = (ArrayList)objectTeam2;
Team[] commonList = new Team[5];
int i = 0;
for(Team x:team1)
{
for(Team y:team2)
{
comparisonCount++;
if(x.compareTo(y) == 0)
{
commonList[i] = x;
System.out.println(commonList[i].teamName);
i++;
break; /*to ensure it looks for only one match per entry*/
}
}
}
return commonList;
}
public int getComparisons()
{
return comparisonCount;
}
}
Team.java
package test;
public class Team implements Comparable<Team> {
String teamName = new String();
public void setName ( String n ) {
teamName = n;
}
public Team(String n) {
setName(n);
}
public int compareTo(Team x)
{
if(this.teamName.equals(x.teamName))
{
return 0;
}
else
{
return -1;
}
}
}
That is a very unfortunate and odd way of passing the arguments, but anyway, to make it work, you can do:
#SuppressWarnings("unchecked")
ArrayList<Team> team1 = (ArrayList<Team>)collections[0];
#SuppressWarnings("unchecked")
ArrayList<Team> team2 = (ArrayList<Team>)collections[1];
Your existing code was taking each ArrayList, putting it into a one element array, wrapping that array as a list, creating an ArrayList from it, and trying to view the ArrayList<ArrayList<Team>> as an ArrayList<Team>.
A few other things I see... you don't need to assign these to variables if you're only using them to add to the list:
Team a = new Team("Boston");
...
teamList1.add(a);
You can simply do:
teamList1.add(new Team("Boston"));
You don't need to create the listCollection array separately, because you can create it inline when passing the arguments:
findCommonElements(new Object[] { teamList1, teamList2 });
In your Team class, this:
String teamName = new String();
Should simply be:
String teamName;
In your compareTo method:
public int compareTo(Team x)
{
if(this.teamName.equals(x.teamName))
{
return 0;
}
else
{
return -1;
}
}
That should be:
public int compareTo(Team x)
{
return teamName.compareTo(x.teamName);
}
which is shorter, and honors the compareTo requirement that sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
I have a set of 100 object.
How can i get a subset of 5 objects from this set ?
I'm doing this for now but it only returns me one object
int size = memberSet.size();
Set<Member> randomSet = new HashSet<Member>();
int item = new Random().nextInt(size);
int i = 0;
for(Member mbr : memberSet)
{
if (i == item){
randomSet.add(mbr);
}
i = i + 1;
}
List<Member> list = new LinkedList<Member>(memberSet);
Collections.shuffle(list);
Set<Member> randomSet = new HashSet<Member>(list.subList(0, 5));
Full example:
public static void main(String... args) {
Set<Member> memberSet = new HashSet<Member>();
for (int i = 0; i < 100; i++)
memberSet.add(new Member(i));
List<Member> list = new LinkedList<Member>(memberSet);
Collections.shuffle(list);
Set<Member> randomSet = new HashSet<Member>(list.subList(0, 5));
System.out.println(randomSet);
}
static class Member {
final int value;
public Member(int value) {
this.value = value;
}
#Override
public String toString() {
return "" + value;
}
}
Although #dacwe solution is much better I can't help myself, on joke, to just say put a for(int i=0; i<5; i++) around everything and move out the Set randomSet = new HashSet();
Outside the for loop :