What us the difference between int[][] a = new int[2][3] and int a[][] = new int[][]{{11,12},{13,14,15}}?
I decompiled the .class file and found in the first case, the JVM will use multianwearray to create the array, while in the second case, it will use anewarray.
I think in the first case, JVM will create a continuous space. Am I right?
first case (int[][] a = new int[2][3])
second case (int[][] a = new int[][]{{11,12},{13,14,15}})
I think in the first case, jvm will create a continuous space. Am i right?
No. A multidimensional array is still an array of arrays. And it must be so, because the code that later accesses the array doesn't know how it was created.
Writing
int[][] a = new int[2][3];
allocates the same amount of heap space and the data on the heap has the same structure as if you would write
int[][] a = new int[2][];
a[0] = new int[3];
a[1] = new int[3];
except that the code for the first variant is embedded in the JVM:
https://github.com/openjdk/jdk17u/blob/master/src/hotspot/share/oops/objArrayKlass.cpp#L178 ff
objArrayOop array = allocate(length, CHECK_NULL);
//...
if (length != 0) {
for (int index = 0; index < length; index++) {
ArrayKlass* ak = ArrayKlass::cast(ld_klass);
oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
h_array->obj_at_put(index, sub_array);
}
}
First Case
Creates an array of 2 int arrays, which are of length 3, which are filled with 0s.
| [ ][0] | [ ][1] | [ ][2]
[0][ ] | 0 | 0 | 0
[1][ ] | 0 | 0 | 0
Second Case
Creates a "jagged" array containing { 11, 13 }, and { 13, 14, 15 }. And which contained values are themselves array of ints.
| [ ][0] | [ ][1] | [ ][2]
[0][ ] | 11 | 12 | error
[1][ ] | 13 | 14 | 15
Related
Let's say I was trying to implement Java's ArrayList from scratch. I understand that I would use the data structure known as an array, have to expand its capacity when needed, and keep track of things such as size (number of items in array) and data (the contents of the array).
Because of this size instance variable, when we remove something from the ArrayList, for example removing 4 from 2, 3, 4, 5, we will be left with 2, 3, 5, [empty space], correct? From what I know we will be setting values equal to the next element over, so not actually downsizing the array, only expanding it if we need to.
If my question is unclear, I am just looking for the remove(Object element) implementation for ArrayList.
I wish I had a diagram for this explanation. If anything else is needed please ask. Thank you.
I had similar doubt in C lang when i was preparing for my GATE(Graduate Aptitude Test in Engineering) exam in 2016.
Well, I had enhanced my coding skills from that time and now i do code in Java.
According to List API
Removes the element at the specified position in this list (optional
operation). Shifts any subsequent elements to the left (subtracts one
from their indices). Returns the element that was removed from the
list.
The ArrayList class is an array-based implementation of the List interface. Specifically, all elements of an ArrayList are stored in a Java array.
The implementation of Arraylist.remove(E) is as follows:
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc(garbage collector) do its work
return oldValue;
}
Where elementData is the backing element array.
In words, it's not so much a shift, as it is a copy of elements, minus the element missing.
Given elementData with 4 elemetns
[ 2 | 3 | 4 | 5 ]
Now removing element at index 2
resulting in
[ 2 | 3 | 5 | null ]
ArrayList.get(2) would result in 5
This is pretty easy and explain why ArrayList shold not be used when it's planned to remove not last elements.
There're 2 parts of ArrayList: internal array (default size is 10 - ArrayList.DEFAULT_CAPACITY = 10) and size value (default value is 0).
Note 1. When you can predict maximum size of ArrayList, do initialize internal array to this size.
List<String> list1 = new ArrayList<>(); // size = 0, internal array Object[] elementData = new Object[10];
List<String> list2 = new ArrayList<>(66); // size = 0, internal array Object[] elementData = new Object[66];
Add element to the end
In case of size == elementData.length -> create new elementData with bigger size and copy all existed data to this new array
Add new elements
size++ (there're many null elements at the end in the array)
Remove element from the end
Remove element (if size > 0)
size--
Remove element from the start or middle
Remove elements
Shift all next elements 1 position right
size--
As you can see, that there's no direct correlation between ArrayList size and length of internal array elementData.
Demo:
List<String> list = new ArrayList<>(4); // [ null | null | null | null ], size = 0
list.add("2"); // [ "2" | null | null | null ], size = 1
list.add("3"); // [ "2" | "3" | null | null ], size = 2
list.add("4"); // [ "2" | "3" | "4" | null ], size = 3
list.add("5"); // [ "2" | "3" | "4" | "5" ], size = 4
list.remove(3); // [ "2" | "3" | "5" | null ], size = 3
list.remove(1); // [ "3" | "5" | null | null ], size = 2
I'm trying to do the following: I have a N size chromosome whose type is IntegerGene. I'm interested in that unique chromosome being evaluated following the crossover operator so I use:
Configuration configuration = new DefaultConfiguration ();
Configuracion.getGeneticOperators (). Clear ();
CrossoverOperator crossover = new CrossoverOperator (configuration);
Configuracion.addGeneticOperator (crossover);
...
Genotype poblacion = Genotype.randomInitialGenotype(configuracion);
For example, I want to use a single chromosome to create the following populations, this chromosome would be | 9 | 5 | 10 | 0 | And therefore I initialize it:
Gene [] genes = new Gene [4];
genes [0] = new IntegerGene (configuration, 9,9);
genes [1] = new IntegerGene (configuration, 5,5);
genes [2] = new IntegerGene (configuration, 10,10);
genes [3] = new IntegerGene (configuration, 0,0);
When I run the program the output (the chromosome solution) is always the same (| 9 | 5 | 10 | 0 |), it does not perform the crossover operator ....
Run:
Population Size: 10
...
9 5 10 0
Punctuation = 12.5
9 5 10 0
Punctuation = 12.5
9 5 10 0
Punctuation = 12.5
9 5 10 0
Punctuation = 12.5
Chromosome Solution [0] = 9
Chromosome Solution [1] = 5
Chromosome Solution [2] = 10
Chromosome Solution [3] = 0
Thank you.
The program has an input a list of doubles and the output needs to be a string containing the list values grouped by their value. The list values will be grouped if they are equal.
Something like:
input 9,77,5,5,31 => output 9 77 2*5 31
I created an algorithm in C# (in Java I think that is almost the same) for this but I am not sure if it can be improved regarding its speed or code quaility, or if it has some bugs that I could not see. The algorithm having also some more input, output examples is below.
List<double> input = new List<double> { 11, 32, 32, 43}; // output 11 2*32 43
//List<double> input = new List<double> { 11, 11, 43, 43 }; // output 2*11 2*43
//List<double> input = new List<double> { 10, 11, 12, 13, 14, 15, 16 }; // output 10 11 12 13 14 15 16
//List<double> input = new List<double> { 11, 11, 11, 11, 11 }; // output 5 * 11
//List<double> input = new List<double> { 11, 11, 32, 22, 22, 22, 4, 10, 10 }; // output 2*11 32 3*22 4 2*10
string listAsString = string.Empty;
double nextElem = double.MinValue;
for (int i = 0; i < input.Count; i++)
{
double currentElem = input[i];
if (i + 1 < input.Count)
{
nextElem = input[i + 1];
}
int equalCount = 0;
while (currentElem.Equals(nextElem) && i < input.Count)
{
equalCount++;
i++;
currentElem = nextElem;
if (i < input.Count)
{
nextElem = input[i];
}
}
if (equalCount < 2)
{
listAsString += currentElem + " ";
}
else
{
listAsString += equalCount + "*" + currentElem + " ";
i--;
}
}
Console.WriteLine(listAsString);
Please let me know if you noticed some bugs or see some improvements that can be done.
Also if you know another implementation of this requirement please add it so that a comparation regarding results, speed, code quality between the algorithms can be done... and find the best way to handle this.
Since the requirement is to group only consecutive equal values, the Dictionary and LINQ GroupBy approaches mentioned in another answer do not apply because they will produce incorrect result for input sequence like 1,2,1. Also there is no standard LINQ method for doing such grouping (except eventually Aggregate method, but it's no more than inefficient for / foreach loop equivalent).
Shortly, your algorithm is the best for such task. But implementation is not.
The main bottleneck is the string concatenation as mentioned by Peroxy, which (also mentioned in the other answer) is easily fixable by utilizing the StringBuilder class. Once you do that, the performance will be just fine.
The other issue I see in the implementation is usage of special values (double.MinValue), duplicate corner case checks, decrementing for loop variable inside the body etc. So although it probably works and I don't see directly a bug, it's kind of hard to follow the algorithm logic and spot a potential bug just reading the implementation. The algorithm itself is quite simple, I would implement it this way:
static string ListAsString(List<double> input)
{
var sb = new StringBuilder();
for (int i = 0; i < input.Count; )
{
var value = input[i];
int count = 1;
while (++i < input.Count && input[i] == value)
count++;
if (sb.Length > 0) sb.Append(' ');
if (count > 1) sb.Append(count).Append('*');
sb.Append(value);
}
return sb.ToString();
}
which IMO is quite easier to follow. Note that there is no duplicate code, no special values and the loop variable i advancing is done only in one place inside the outer loop body. Again, this has nothing to do with performance (which is provided by the StringBuilder usage), but simply readability, redundancy elimination and less error prone.
Personally, I see great potential with Dictionary usage here, here is a quick solution I made with a dictionary implementation:
var input = new List<double> { 9, 77, 5, 5, 31 };
var dict = new Dictionary<double, int>();
var listAsString = new StringBuilder();
foreach (var item in input)
{
if (dict.ContainsKey(item))
dict[item]++;
else
dict[item] = 1;
}
foreach (var item in dict)
{
listAsString.Append(item.Value > 1 ? $"{item.Value}*{item.Key} " : $"{item.Key} ");
}
Console.WriteLine(listAsString);
If you ever wanted a non efficient LINQ one liner solution:
string result = string.Join(" ", input.GroupBy(i => i)
.Select(x =>
x.Count() > 1 ?
$"{x.Count()}*{x.Key} " :
$"{x.Key} "));
However, I believe your method is written nicely, albeit a bit less readable than the dictionary one, but the main flaw with your solution is that you are using a string when building the final string, you should definitely be using a StringBuilder, I have introduced the StringBuilder in your method and made comparisons between these three methods:
Dictionary | Your method | GroupBy method
------------------------------------------------
2 ms | 0 ms | 5 ms n=3
0 ms | 0 ms | 0 ms n=6
0 ms | 0 ms | 0 ms n=12
0 ms | 0 ms | 0 ms n=24
0 ms | 0 ms | 0 ms n=48
0 ms | 0 ms | 0 ms n=96
0 ms | 0 ms | 0 ms n=192
0 ms | 0 ms | 0 ms n=384
0 ms | 0 ms | 0 ms n=768
0 ms | 0 ms | 0 ms n=1536
1 ms | 0 ms | 1 ms n=3072
3 ms | 2 ms | 3 ms n=6144
5 ms | 4 ms | 6 ms n=12288
8 ms | 7 ms | 14 ms n=24576
14 ms | 13 ms | 25 ms n=49152
31 ms | 32 ms | 66 ms n=98304
80 ms | 59 ms | 146 ms n=196608
149 ms | 123 ms | 294 ms n=393216
246 ms | 218 ms | 504 ms n=786432
483 ms | 428 ms | 1040 ms n=1572864
999 ms | 873 ms | 2070 ms n=3145728
1995 ms | 1784 ms | 3950 ms n=6291456
Your solution is always the fastest, if you want to go for speed, keep your solution, but change it to use StringBuilder, use listAsString.Append(currentElem + " ") instead of listAsString += currentElem + " ".
GroupBy could be used if you will only operate with collections that have n < 1000, use the Dictionary solution if you would rather settle with readability over speed.
So I have a document on excel and I have a list of data saying how many people use x or y and how many times. So basically i have a column with people ID, a column with type (x and y) then a column saying how many times the people use x or y. I want to be able to iterate through the list without changing it so as it get the number of people using each type and i want the list to be sorted in ascending order or frequency. So I wanted to use a for loop to go through the list and put an if statement inside of it saying that if x, then another for loop to be able to group them by frequency.
The actual code I have is not good but I am really stuck on that and do not really know how to proceed :
for(int i = 0; i < type1.size(); i++){
if(events.get(i).isX()){
for(int j = 0; j < /*max value of the data in the list*/; j++ )
//here list should group all common frequency
}
else
//do same thing but for y
Excel table eg
QUESTION
Under the assumption that you have an excel-file with three columns:
id | type | frequency
And a List representing the data of your excel-file. You might want to order your Entrys with the Collections.sort(Comparator<T>) method.
Here is an example on how you can achieve that:
Example a:
Arraylist<Row> yourList = new ArrayList();
fillListWithExlData(yourList);
for(int i = 0; i < yourList.size(); i++){
Collections.sort(yourList, new Comparator<Row>()){
//compares row i with the following row
compare(Row oneRow, Row followingRow){
//if the result is 1 =< the entry moves on higher in the list if the result is = 0 it stays on its position and if its <= -1 it moves down.
return oneRow.getFrequenzy() - followingRow.getFrequenzy();
}
});
}
Notice: that you can also use the Comparator to order your "types".
Example b:
return (oneRow.getType() == followingRow.getType()) ? 0 : -1;
Or you might even want to match both, id and frequency. Then you might try this:
Example c:
return (oneRow.getType() == followingRow.getType() &&
oneRow.getFrequenzy() == followingRow.getFrequenzy())
? 0 : -1;
example a should Order a potential List:
id | type | frequency
1 | x | 12
2 | y | 10
3 | x | 12
into:
id | type | frequency
1 | x | 12
3 | x | 12
2 | y | 10
I'm working on an textbook assignment and am having trouble understanding arrays. I'm looking at a practice question and am confused.
Declare an array of integers containing the first five prime numbers.
This would be int[]primes = {2,3,5,7,11}
Assume the array 'primes' has been initialized. What does it contain after executing the following loop?
for(int i = 0; i < 2; i++)
{
primes[4 - i] = primes[i];
}
The textbook gives the answer {2,3,5,3,2} for this...can anyone explain how this loop works?
I assume you understand practice 1. For practice 2, the loop
for (int i = 0; i < 2; i++)
iterates twice: once at i=0, and once at i=1. At i=2, the condition i<2 is broken, and the loop does not execute.
The actual line of code inside the loop
primes[4-i] = primes[i];
sets the 4-i'th element in the array to be equal to the i'th element in the array.
Initialized, the array primes is {2,3,5,7,11}
After one loop, the array primes is {2,3,5,7,2} (primes[4] = primes[0] has been executed).
After both loops, the array primes is {2,3,5,3,2} (primes[3] = primes[1] has been executed).
Remember that arrays are indexed by zero. Hope this helped.
the for loop exceutes two times, for i=0 and i=1
primes[4-0] = primes[0] = 2 -> primes[4] = 2
primes[4-1] = primes[1] = 3 -> primes[3] = 3
so the first 3 fields in the array are not changed, just the 4th and the 5th
It seems like you don't understand for loops that well at all, since this is a pretty simple example. For loops are basically shortcuts in code that iterate through data structures. You can type out for loops line by line, but they would be way longer. In this example,
for (int i = 0; i < 2; i++)
{
primes[4 - i] = primes[i];
}
becomes:
primes[4 - 0] = primes[0];
primes[4 - 1] = primes[1];
So all this loop is doing is setting the last element of the array to the first, and the second-to-last element to the second.
Starting with
int[]primes = {2,3,5,7,11}
the for-loop works like this
i=0 -> primes[4-0] = primes[0]; //array {2,3,5,7,2}
i=1 -> primes[4-1] = primes[1]; //array {2,3,5,3,2}
Imagine you have a zoo(memory) with a row of cages(array) next to each other. each cage is the exact size needed to hold an animal(data type like int)
Zoo---------------------
[animal][animal][animal][animal][animal]
------------------------
You decide to label each cage with a number(index)
Zoo---------------------
[animal][animal][animal][animal][animal]
0 1 2 3 4
------------------------
You get some initial funding to purchase animals for your cages (initialize the array). So you buy a Zebra, Panda, Owl, Tiger, and a Bear and put them in the cages. The order you purchased the animals is the order you place them in their cages.
Zoo---------------------
[Zebra][Panda][Owl][Tiger][Bear]
0 1 2 3 4
------------------------
Your zoo just perfected cloning so you are able to make copies of the animals. You Decide people are really enjoying Pandas & Zebras but don't care for Tigers and Bears. You delegate your tasks(algorithm) by having a sequential stack of index cards with instructions(loop). Each index card has a page number going from 0 up to less than 2, so your last index card has the page number 1
_________________________ ___________________________
|0 | |1 |
| | | |
| | | |
| | | |
| | | |
|_________________________| |___________________________|
You love the number 4 and believe that it is way better then any number and should be the starting point of counting instead of the number 0. So you give all instructions using the number 4 as a reference point.
_____________________________ _____________________________
|0 | |1 |
|Yo zoo keeper, | |Yo zoo keeper, |
|Copy the animal | |Copy the animal |
|in the cage that has this | |in the cage that has this |
|card number and put it in | |card number and put it in |
|cage 4 minus this card number| |cage 4 minus this card number|
|-The Boss | |-The Boss |
|_____________________________| |_____________________________|
Your zoo keeper reads the first index card(with the number 0). He makes a copy of the Zebra and puts in the cage with the Bear. The Zebra immediately eats the bear and is the only inhabitant of the cage.
Zoo---------------------
[Zebra][Panda][Owl][Tiger][Zebra]
0 1 2 3 4
------------------------
Your zoo keeper reads the second index card(with the number 1). He makes a copy of the Panda and puts in the cage with the Tiger. The Panda immediately eats the Tiger and is the only inhabitant of the cage.
Zoo---------------------
[Zebra][Panda][Owl][Panda][Zebra]
0 1 2 3 4
------------------------
And that is how arrays work for primitives. For Objects instead of cages in your zoo you just have a map that points to where you can find the animals in the zoo. Any animal that is not on the list gets marked with a tag and swept to the wild, freeing up space in your zoo.