Attempting to tidy up code, originally I was using this method of writing to arrays, which is ridiculously long when I have to repeat it 20 times
if (ant.getAntNumber() == 3)
{
numbers3.add(ant.getCol());
numbers3y.add(ant.getRow());
}
if (ant.getAntNumber() == 4)
{
numbers4.add(ant.getCol());
numbers4y.add(ant.getRow());
}
I attempted to use a for loop to do it but I cant figure out how to add to the array using the string value, because it thinks its a string rather than trying to use the array
for (int j = 0; j<maxAnts; j++)
{
String str = "numbers" + j;
String str2 = "numbers" + j + "y";
//this part doesnt work
str.add(ant.getCol());
}
Any suggestions would be helpful
In Java, you cannot use the value of a String object to reference an actual variable name. Java will think you're attempting to to call add on the String object, which doesn't exist and gives you the compiler error you're seeing.
To avoid the repetition, you need to add your Lists to two master lists that you can index.
In your question, you mention arrays, but you call add, so I'm assuming that you're really referring to Lists of some sort.
List<List<Integer>> numbers = new ArrayList<List<Integer>>(20);
List<List<Integer>> numbersy = new ArrayList<List<Integer>>(20);
// Add 20 ArrayList<Integer>s to each of the above lists in a loop here.
Then you can bounds-check ant.getAntNumber() and use it as an index into your master lists.
int antNumber = ant.getAntNumber();
// Make sure it's within range here.
numbers.get(antNumber).add(ant.getCol());
numbersy.get(antNumber).add(ant.getRow());
How about this?
Ant[] aAnt = new Ant[20];
//Fill the ant-array
int[] aColumns = new int[aAnt.length];
int[] aRows = new int[aAnt.length];
for(int i = 0; i < aAnt.length; i++) {
aColumns[i] = aAnt[i].getCol();
aRows[i] = aAnt[i].getRow();
}
or with lists:
List<Integer> columnList = new List<Integer>(aAnt.length);
List<Integer> rowList = new List<Integer>(aAnt.length);
for(Ant ant : aAnt) {
columnList.add(ant.getCol());
rowList.add(ant.getRow());
}
or with a col/row object:
class Coordinate {
public final int yCol;
public final int xRow;
public Coordinate(int y_col, int x_row) {
yCol = y_col;
xRow = x_row;
}
}
//use it with
List<Coordinate> coordinateList = new List<Coordinate>(aAnt.length);
for(Ant ant : aAnt) {
coordinateList.add(ant.getCol(), ant.getRow());
}
A straight-forward port of your code would be to use two Map<Integer, Integer> which store X and Y coordinates. From your code it seems like ant numbers are unique, i.e., we only have to store a single X and Y value per ant number. If you need to store multiple values per ant number, use a List<Integer> as value type of the Map instead.
Map<Integer, Integer> numbersX = new HashMap<Integer, Integer>();
Map<Integer, Integer> numbersY = new HashMap<Integer, Integer>();
for(Ant ant : ants) {
int number = ant.getAntNumber();
numbersX.put(number, ant.getCol());
numbersY.put(number, ant.getRow());
}
Related
my program is reading large txt files(in MBs) which contain the source ip and destination ip(for example 192.168.125.10,112.25.2.1) ,,,Here read is an ArrayList in which the data is present.
i have generated unique ids(uid int type) using srcip and destip and now i am storing in
static ArrayList<Integer[]> prev = new ArrayList<Integer[]>();
where Array is
:-
static Integer[] multi1;
multi1 = new Integer[]{(int)uid,count,flag};
i have to print the all uids with there count or their frequencies using hashmap.
Plz give some solution...
for (ArrayList<String> read : readFiles.values())
{
if(file_count<=2)
{
for(int i=0 ; i<read.size() ; i++)
{
String str1=read.get(i).split(",")[0];//get only srcIP
String str2=read.get(i).split(",")[1];//get only destIP
StringTokenizer tokenizer1=new StringTokenizer(str1,".");
StringTokenizer tokenizer2=new StringTokenizer(str2,".");
if(tokenizer1.hasMoreTokens()&&tokenizer2.hasMoreTokens())
{
sip_oct1=Integer.parseInt(tokenizer1.nextToken());
sip_oct2=Integer.parseInt(tokenizer1.nextToken());
sip_oct3=Integer.parseInt(tokenizer1.nextToken());
sip_oct4=Integer.parseInt(tokenizer1.nextToken());
dip_oct1=Integer.parseInt(tokenizer2.nextToken());
dip_oct2=Integer.parseInt(tokenizer2.nextToken());
dip_oct3=Integer.parseInt(tokenizer2.nextToken());
dip_oct4=Integer.parseInt(tokenizer2.nextToken());
uid=uniqueIdGenerator(sip_oct1,sip_oct2,sip_oct3,sip_oct4,dip_oct1,dip_oct2,dip_oct3,dip_oct4);
}
multi1 = new Integer[]{(int)uid,count,flag};
prev.add(multi1);
System.out.println(prev.get(i)[0]);//getting uids from prev
Map<ArrayList<Integer []> , Integer> map = new HashMap<ArrayList<Integer[]>, Integer>();
for (int j=0 ; j<prev.size() ; j++)
{
Integer temp=map.get(prev.get(i)[0]);
count = map.get(temp);
map.put(temp, (count == null) ? 1 : count++);
}
printMap(map);
System.out.println("uids--->"+prev.get(i)[0]+" Count--- >"+count+" flag--->"+prev.get(i)[2]);
}
}
file_count++;
}
}
public static void printMap(Map<ArrayList<Integer[]>, Integer> map)
{
for (Entry<ArrayList<Integer[]>, Integer> entry : map.entrySet())
{
System.out.println(" Value : "+ entry.getValue()+"key : "+entry.getKey());
}
}
public static double uniqueIdGenerator(int oc1,int oc2,int oc3,int oc4,int oc5,int oc6,int oc7,int oc8)
{
int a,b;
double c;
a=((oc1*10+oc2)*10+oc3)*10+oc4;
b=((oc5*10+oc6)*10+oc7)*10+oc8;
c= Math.log(a)+Math.log(b);
return Math.round(c*1000);
}
Now understanding what you want, there are (at least) 2 ways of doing this.
1st: Make a list with the uid's. Then a second list where you can have a value (your uid) and keep a count. Was thinking of HashMap, but there you can not easily change the count. Maybe an ArrayList of a list with 2 values.
Then loop over your list with the uid's, check with a second for loop if the uid is already in the second list. If it is, add one to the count. If it is not, add it to the list.
2nd: Do the same thing, but then with classes (very Java). Then you can put even more info into the class ;)
Hope this helps!
*edit: #RC. indeed gives cleaner code.
So I need to choose between
HashMap<String[], Object>
HashMap<ArrayList<String>,Object>
My input Parameter is: ArrayList<String> in.
The whole ArrayList<String> in cannot be the key, since it does contain elements, which are not supposed to be like a Primary Key in a database. I do know, that the first n elements of the incoming ArrayList<String> in supposed to be the primary Keys.
Which one would be faster?
Scenario:
HashMap<ArrayList<String>, Object> hmAL = new HashMap<>();
HashMap<String[], Object> hmSA = new HashMap<>();
ArrayList<String> in = new ArrayList<>();
fillWithStuff(in);
//Which one would be faster?
getObject(in,hmAL,5);
getObject(in,hmSA,5);
With Option 1:
private Object getObject(ArrayList<String> in, HashMap<ArrayList<String>, Object> hm, int n){
return hm.get(in.sublist(0,n));
}
With Option 2:
private Object getObject(ArrayList<String> in, HashMap<String[], Object> hm, int n){
String[] temp = new String[n];
for(int i=0; i<n; i++)
temp[i]=in.get(i);
return hm.get(temp);
}
Considering:
Which is faster? Short the list, or copy to an array?
I'm wondering, which hash (since it is a HashMap) would be faster. Hashing of a ArrayList, or an equal-sized array. Or doesn't it make any difference?
Using String[] is not a good idea because it does not implement hashCode(). This means if you have 2 string arrays which are different objects but with the exact same values, the map will not find it.
The implementation of 'hashCode` seems to use each of the string elements hashcode so the lookup in a map would succeed. So I'd go with this one.
That said, I would rather build a key myself based on the objects in the list.
Dealing with copying only
The subList method is implemented very efficiently in Java 7+, not requiring any copying at all. It simply returns a view directly onto the original array. Thus, in Java 7+, it will be faster than the copy element by element method. However, in Java 6, both ways are essentially equivalent.
Dealing with the method as a whole
If you look at the whole method, your choice is no longer a choice. If you want the method to function, you will have to use the first implementation. Array hashCode() does not look at the elements inside it---only the identity of the array. Because you are creating the array in your method, the Map.get() will necessary return null.
On the other hand, the List.hashCode() method runs a hash on all of the contained elements, meaning that it will successfully match if all of the contained elements are the same.
Your choice is clear.
Just to add on above two answers, I have tested in Java 7 and found on an average with list it's 50 times faster with 2000000 total elements and 1000000 elements which participate in calculating hashcode i.e. primary keys (hypothetical number). Below is the program.
public class TestHashing {
public static void main(String[] args) {
HashMap<ArrayList<String>, Object> hmAL = new HashMap();
HashMap<String[], Object> hmSA = new HashMap<>();
ArrayList<String> in = new ArrayList<>();
fillWithStuff(in);
// Which one would be faster?
long start = System.nanoTime();
getObject(in, hmAL, 1000000);
long end = System.nanoTime();
long firstTime = (end-start);
System.out.println("firstTime :: "+ firstTime);
start = System.nanoTime();
getObject1(in, hmSA, 1000000);
end = System.nanoTime();
long secondTime = (end-start);
System.out.println("secondTime :: "+ secondTime);
System.out.println("First is faster by "+ secondTime/firstTime);
}
private static void fillWithStuff(ArrayList<String> in) {
for(int i =0; i< 2000000; i++) {
in.add(i+"");
}
}
private static Object getObject(ArrayList<String> in,
HashMap<ArrayList<String>, Object> hm, int n) {
return hm.get(in.subList(0, n));
}
private static Object getObject1(ArrayList<String> in, HashMap<String[], Object> hm, int n){
String[] temp = new String[n];
for(int i=0; i<n; i++)
temp[i]=in.get(i);
return hm.get(temp);
}
}
Output
firstTime :: 218000
secondTime :: 11627000
First is faster by 53
I have 3 arraylist each have size = 3 and 3 arrays also have length = 3 of each. I want to copy data from arraylists to arrays in following way but using any loop (i.e for OR for each).
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
I have done it manually one by one without using any loop, but code appears to be massive because in future I'm sure that number of my arraylists and arrays will increase up to 15.
I want to copy the data from arraylists to arrays as shown in the image but using the loops not manually one by one?
How about this?
List<Integer> arraylist0 = Arrays.asList(2,4,3);
List<Integer> arraylist1 = Arrays.asList(2,5,7);
List<Integer> arraylist2 = Arrays.asList(6,3,7);
List<List<Integer>> arraylistList = Arrays.asList(arraylist0, arraylist1, arraylist2);
int size = 3;
int[] myArray0 = new int[size];
int[] myArray1 = new int[size];
int[] myArray2 = new int[size];
int[][] myBigArray = new int[][] {myArray0, myArray1, myArray2};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
myBigArray[i][j] = arraylistList.get(j).get(i);
}
}
To explain, since we want to be able to work with an arbitrary size (3, 15, or more), we are dealing with 2-dimensional data.
We are also dealing with array and List, which are slightly different in their use.
The input to your problem is List<Integer>, and so we make a List<List<Integer>> in order to deal with all the input data easily.
Similarly, the output will be arrays, so we make a 2-dimensional array (int[][]) in order to write the data easily.
Then it's simply a matter of iterating over the data in 2 nested for loops. Notice that this line reverses the order of i and j in order to splice the data the way you intend.
myBigArray[i][j] = arraylistList.get(j).get(i);
And then you can print your answer like this:
System.out.println(Arrays.toString(myArray0));
System.out.println(Arrays.toString(myArray1));
System.out.println(Arrays.toString(myArray2));
You need to have two additional structures:
int[][] destination = new int [][] {myArray1, myArray2,myArray3 }
List<Integer>[] source;
source = new List<Integer>[] {arraylist1,arraylist2,arraylist3}
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
for (int i=0;i<destination.length;i++) {
for (int j=0;j<source.length;j++) {
destination[i][j] = source[j].get(i);
}
}
If you cannot find a ready made API or function for this, I would suggest trivializing the conversion from List to Array using the List.toArray() method and focus on converting/transforming the given set of lists to a another bunch of lists which contain the desired output. Following is a code sample which I would think achieves this. It does assume the input lists are NOT of fixed/same sizes. Assuming this would only make the logic easier.
On return of this function, all you need to do is to iterate over the TreeMap and convert the values to arrays using List.toArray().
public static TreeMap<Integer, List<Integer>> transorm(
List<Integer>... lists) {
// Return a blank TreeMap if not input. TreeMap explanation below.
if (lists == null || lists.length == 0)
return new TreeMap<>();
// Get Iterators for the input lists
List<Iterator<Integer>> iterators = new ArrayList<>();
for (List<Integer> list : lists) {
iterators.add(list.iterator());
}
// Initialize Return. We return a TreeMap, where the key indicates which
// position's integer values are present in the list which is the value
// of this key. Converting the lists to arrays is trivial using the
// List.toArray() method.
TreeMap<Integer, List<Integer>> transformedLists = new TreeMap<>();
// Variable maintaining the position for which values are being
// collected. See below.
int currPosition = 0;
// Variable which keeps track of the index of the iterator currently
// driving the iteration and the driving iterator.
int driverItrIndex = 0;
Iterator<Integer> driverItr = lists[driverItrIndex].iterator();
// Actual code that does the transformation.
while (driverItrIndex < iterators.size()) {
// Move to next driving iterator
if (!driverItr.hasNext()) {
driverItrIndex++;
driverItr = iterators.get(driverItrIndex);
continue;
}
// Construct Transformed List
ArrayList<Integer> transformedList = new ArrayList<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
transformedList.add(iterator.next());
}
}
// Add to return
transformedLists.put(currPosition, transformedList);
}
// Return Value
return transformedLists;
}
I have two hashmap
LinkedHashMap<String, int[]> val1 = new LinkedHashMap<String, int[]>();
LinkedHashMap<String, int> val2 = new LinkedHashMap<String, int>();
each hashmap has different key and values. I am trying to iterate over both hashmap
at the same time and multiply each value of val1->int[] to val2->int
What is the easiest and fasted way to do it? I have thousands values in both hashmap.
Thanks
You are probably doing it wrong...
First, a HashMap can't store ints, it needs proper objects - like Integer
– An array is an object, although it's hidden behind some syntactic sugar.
Here's how to loop over both maps, if they happens to have the same size,
which is what I think you mean.
Iterator<int[]> expenses = val1.values().iterator();
Iterator<Integer> people = val2.values().iterator();
assert val1.size() == val2.size() : " size mismatch";
while (expenses.hasNext()) {
int[] expensesPerMonth = expenses.next();
int persons = people.next();
// do strange calculation
int strangeSum = 0;
for (int idx = 0; idx < expensesPerMonth.length; idx++) {
strangeSum += persons * expensesPerMonth[idx];
}
System.out.println("strange sum :" + strangeSum);
}
But You should probably go back and rethink how you store your data –
why are you using maps, and whats the key?
Wouldn't it be better to create an object that represents the combination of monthly expenses and number of people, for instance?
AFAIK, a LinkedHashMap has iteration ordering. So, something like this may work:
Iterator myIt1 = val1.entrySet().iterator();
Iterator myIt2 = val2.entrySet().iterator();
while(val1.hasNext() && val2.hasNext()) {
int myarray[] = val1.next();
for(int i = 0; i<myarray.length; i++) {
myarray[i] = myarray[i] * val2.next();
}
}
I have a List with say size n, and I have to dynamically create n variables ie i want to dynamically create the variables depending upon the size of the list. How can i achieve this?
Say i have List as List<Integer> year with n elements in it;
then i have to create the n Integer variables from the above list.
EDIT : If i have list with 3 elements in it the i want to create 3 variables like
a = list(0);
b = list(1);
c = list(2);
like this the list may have any number of elements then i have to create those many variables. Hope I am clear now.
thanks.
You can not create n local variables as you seem to suggest. (What would their names be?)
You need to store the variables (or rather integer values) in a List or some other Collection, and populate them within a loop:
int n = year.size();
List<Integer> theIntegers = new ArrayList<Integer>(n);
for (int i = 0; i < n; i++)
theIntegers.add(i);
gives you year.size() number of integers (0, 1, 2, ...).
You can then access the integers through
theIntegers.get(4);
if you want to read the integer with index 4. and
theIntegers.set(4, 10);
if you want to update the integer with index 4, to the value 10.
You could in this case also create an array:
int[] ints = new int[year.size()];
for (int i = 0; i < ints.length; i++)
ints[i] = i;
There is no way I know of in Java to dynamically add variables to a scope. You can use a map as a type of variable... well, mapping instead:
final List<Integer> years = getYearList();
final Map<String, Integer> yearMapping = new HashMap<String, Integer>();
for(int year : years)
{
final String name = generateNameForYear(year);
yearMapping.add(name, new Integer(year));
}
// Later... Get "variables" out of the map:
final String variableName = "fooYear";
if (yearMapping.containsKey(variableName))
{
final Integer variableValue = yearMapping.get(variableName);
}
else
{
// "variable" does not exist.
}