Related
I have a rank 3 int array array[9][3][3] and I want to convert it into a rank 2 array arrayConvt[9][9] by removing the major axis (rather than the middle axis). To make a 9x9 array rather than 3x27, imagine array broken up into 3 equal parts, each laid out into arrayConvt before the next. Note that the middle arrays (array[i]) do not remain contiguous in arrayConvt, but the innermost arrays (array[i][j]) do.
One way to visualize it is to look at array as an array of 9 blocks. I want to recombine the blocks left-to-right, top-to-bottom:
How can I reshape array according to this mapping?
The code sample below provides data to work with and the desired result:
public static void main(String[] args) {
int[][][] array = {
{
{0, 1, 2},
{10, 11, 12},
{20, 21, 22}
},
{
{100, 101, 102},
{110, 111, 112},
{120, 121, 122}
},
{
{200, 201, 202},
{210, 211, 212},
{220, 221, 222}
},
{
{300, 301, 302},
{310, 311, 312},
{320, 321, 322}
},
{
{400, 401, 402},
{410, 411, 412},
{420, 421, 422}
},
{
{500, 501, 502},
{510, 511, 512},
{520, 521, 522}
},
{
{600, 601, 602},
{610, 611, 612},
{620, 621, 622}
},
{
{700, 701, 702},
{710, 711, 712},
{720, 721, 722}
},
{
{800, 801, 802},
{810, 811, 812},
{820, 821, 822}
}
};
int[][] arrayConvt;
/*****
* What should go here to fill out `arrayConvt` using entries from `array` so it's equivalent to `array2d` below?
*/
int[][] array2d = {
{ 0, 1 , 2, 100, 101, 102, 200, 201, 202},
{ 10, 11, 12, 110, 111, 112, 210, 211, 212},
{ 20, 21, 22, 120, 121, 122, 220, 221, 222},
{300, 301, 302, 400, 401, 402, 500, 501, 502},
{310, 311, 312, 410, 411, 412, 510, 511, 512},
{320, 321, 322, 420, 421, 422, 520, 521, 522},
{600, 601, 602, 700, 701, 702, 800, 801, 802},
{610, 611, 612, 710, 711, 712, 810, 811, 812},
{620, 621, 622, 720, 721, 722, 820, 821, 822}
};
}
Try this.
public static void main(String[] args) {
int[][][] array = {
{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}},
{{10, 11, 12}, {13, 14, 15}, {16, 17, 18}},
{{20, 21, 22}, {23, 24, 25}, {26, 27, 28}},
{{30, 31, 32}, {33, 34, 35}, {36, 37, 38}},
{{40, 41, 42}, {43, 44, 45}, {46, 47, 48}},
{{50, 51, 52}, {53, 54, 55}, {56, 57, 58}},
{{60, 61, 62}, {63, 64, 65}, {66, 67, 68}},
{{70, 71, 72}, {73, 74, 75}, {76, 77, 78}},
{{80, 81, 82}, {83, 84, 85}, {86, 87, 88}},
};
int[][] arrayConv = new int[9][9];
int[][] s = {
{0, 0}, {0, 3}, {0, 6},
{3, 0}, {3, 3}, {3, 6},
{6, 0}, {6, 3}, {6, 6},
};
for (int i = 0, p = 0; i < 9; ++i, ++p)
for (int j = 0, r = s[p][0]; j < 3; ++j, ++r)
for (int k = 0, c = s[p][1]; k < 3; ++k, ++c)
arrayConv[r][c] = array[i][j][k];
for (int[] r : arrayConv)
System.out.println(Arrays.toString(r));
}
output:
[0, 1, 2, 10, 11, 12, 20, 21, 22]
[3, 4, 5, 13, 14, 15, 23, 24, 25]
[6, 7, 8, 16, 17, 18, 26, 27, 28]
[30, 31, 32, 40, 41, 42, 50, 51, 52]
[33, 34, 35, 43, 44, 45, 53, 54, 55]
[36, 37, 38, 46, 47, 48, 56, 57, 58]
[60, 61, 62, 70, 71, 72, 80, 81, 82]
[63, 64, 65, 73, 74, 75, 83, 84, 85]
[66, 67, 68, 76, 77, 78, 86, 87, 88]
First, construct some source data
int src[][][] = new int[9][3][3];
for (int r = 0; r < 9; r++) {
for (int rr = 0; rr < 3; rr++) {
for (int cc = 0; cc < 3; cc++) {
src[r][rr][cc] = r * 9 + rr * 3 + cc + 1;
}
}
}
for (int[][] d : src) {
System.out.println(Arrays.deepToString(d));
}
prints
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[10, 11, 12], [13, 14, 15], [16, 17, 18]]
[[19, 20, 21], [22, 23, 24], [25, 26, 27]]
[[28, 29, 30], [31, 32, 33], [34, 35, 36]]
[[37, 38, 39], [40, 41, 42], [43, 44, 45]]
[[46, 47, 48], [49, 50, 51], [52, 53, 54]]
[[55, 56, 57], [58, 59, 60], [61, 62, 63]]
[[64, 65, 66], [67, 68, 69], [70, 71, 72]]
[[73, 74, 75], [76, 77, 78], [79, 80, 81]]
Now transform the matrix
int[][] dst = transform(src);
for (int[] row : dst) {
System.out.println(Arrays.toString(row));
}
prints
[1, 2, 3, 10, 11, 12, 19, 20, 21]
[4, 5, 6, 13, 14, 15, 22, 23, 24]
[7, 8, 9, 16, 17, 18, 25, 26, 27]
[28, 29, 30, 37, 38, 39, 46, 47, 48]
[31, 32, 33, 40, 41, 42, 49, 50, 51]
[34, 35, 36, 43, 44, 45, 52, 53, 54]
[55, 56, 57, 64, 65, 66, 73, 74, 75]
[58, 59, 60, 67, 68, 69, 76, 77, 78]
[61, 62, 63, 70, 71, 72, 79, 80, 81]
sr,sc - the source row and column of the inner 3x3 matrix to copy
r - the destination row to contain the above
the outer loop is used to create the destination row as well as allow
intermediate increments of key variables
and the JavaDoc explains System.arraycopy
public static int[][] transform(int[][][] src) {
int sr = 0;
int[][] dst = new int[9][9];
for (int x = 0; x < 3; x++) {
for (int sc = 0; sc < 3; sc++) {
int r = x * 3 + sc;
System.arraycopy(src[sr][sc], 0, dst[r], 0, 3);
System.arraycopy(src[sr + 1][sc], 0, dst[r], 3, 3);
System.arraycopy(src[sr + 2][sc], 0, dst[r], 6, 3);
}
sr = sr + 3;
}
return dst;
}
The best way of figuring out how to do this sort of thing is to play around with indices & reshaping, examining the resultant arrays. Once you do this, you notice a few things that can help you come up with more formal approaches.
One is to examine the mapping in terms of array index expressions. Since you want to map array[i][j][k] to arrayConvt[u][v], you need a way of expressing u and v in terms of i, j and k (or vice versa).
Calculate Destination Indices
Let's start with u. Note each array[i][j] remains contiguous in the result. Note also that array[i][j] is followed by array[i+1][j] (rather than array[i][j+1]) until you reach the end of arrayConvt. Thus, array[i..i+2][j] (where i is a multiple of 3), if flattened, becomes arrayConvt[j+x]. The x is present because the range of j doesn't quite match between array and arrayConvt, and so an adjustment is needed. Once the first 3 arrays in arrayConvt are filled, j goes back to 0, but j+x can go on to the next element of arrayConvt. As for where to get x, k is similarly limited in range, but i hasn't run through its range. Since j runs 0..2, it only needs to be combined with a multiple of 3, which we can get with (i / 3) * 3. This gives j + (i / 3)*3, which a quick mental check will show that it runs 0..8. Thus, u = j + (i / 3) * 3.
On to v. First note:
the minor index (k) in array[i][j][k] changes just as rapidly for arrayConvt and
the minor index for arrayConvt is independent of j
Thus v = k + f(i) (where f must be determined). Looking at how each arrayConvt[u] is layed out in terms of k and the 1D arrays from array[i][j] (<1D> #n in the diagram), we see something similar to how u related to i.
v | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
k | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 |
| <1D> #0 | <1D> #1 | <1D> #2 |
i | 3a + 0 | 3a + 1 | 3a + 2 |
f(i) | 0 | 3 | 6 |
We can see that for any row of arrayConvt, i % 3 will range over 0..2. (i % 3) * 3 gives us f(i). Thus v = k + (i % 3) * 3
This gives you a loop over the source array indices, which are mapped to the destination array indices.
int[][] arrayConvt = array[array.length][array[0].length * array[0][0].length];
for (int i = 0; i < array.length; ++i) {
for (int j = 0; j < array[i].length; ++j) {
for (int k = 0; k < array[i][j].length; ++j) {
arrayConvt[j + (i/3)*3][k + (i%3)*3] = array[i][j][k];
}
}
}
Calculate Source Indices
You can take the above expressions for u and v and rewrite them so i, j and k are in terms of u and v. You could also try starting from u and v and examine how i, j and k might come from them. Let's do this, but by a different route: examine the entries in the sample array2d, since i, j and k can be read directly from it (not an accident; by encoding coordinates into the original array and figuring out where each element should get mapped to, the overall mapping is, in effect, created. You could even use this as the basis for the mapping function: loop over the elements of the coordinate array, and use the values & indices to copy from the source to the destination).
k we see increasing left-to-right only (along v), though it wraps around. This is simply v % 3. j increases top-to-bottom (along u) and also wraps around. Thus j = u % 3.
i varies with both u and v. It also occurs in groups of 3 along both axes before changing, so we're looking for something involving u / 3 and v / 3. Lastly, it varies faster along v and jumps by 3 along u, so i = (u / 3) * 3 + (v / 3).
You can loop over the destination array indices, and map the source array indices.
int[][] arrayConvt = array[array.length][array[0].length * array[0][0].length];
for (int u = 0; i < arrayConvt.length; ++i) {
for (int v = 0; j < arrayConvt[i].length; ++j) {
arrayConvt[u][v] = array[ (u / 3) * 3 + (v / 3) ][u % 3][v % 3];
}
}
Beyond the Problem
There's another approach that, once spotted, is even easier to work with. Hidden in the 3D array is a hypercube: array can be viewed as a projection of a 4D array into 3 dimensions. You can realize this in various (equivalent) ways:
envisioning array as 9x3x3, broken into three cubes, you get one fairly common visualization of a projected discrete hypercube (the same as a 3x3x3 discrete cube projected into 2D is 3 3x3 squares).
An MxN array can be represented as an array of 1 lower rank of size M*N by mapping [i][j] to i*N+j (this is how multidimensional arrays are implemented in languages that use contiguous memory for such arrays). Under this mapping, a T[M][N] is equivalent to T[M*N]. Looking at the indices, note that i can be refactored as i = i_0 * 3 + i_1, where i_0 and i_1 range from 0 through 2. Thus, array[9][3][3] is equivalent to a multidimensional array array4d[3][3][3][3].
From this vantage, the problem is a simple reshaping from a rank 4 cube to a rank 2 cube; the main work is:
figuring out the index order from the source
identifying which indices of the destination to map to
With indices h, i, j and k, we have the index expression array[h*3+i][j][k] (note: i is the 3rd dimension, or depth, and h is the 4th, or duration). When mapping, the last index of array remains the last of arrayConvt (the 1st dimension). After completing a loop over k, we advance along the outermost array; in particular, the 3rd dimension, i (the 4th is also along the outermost array but jumps from cube to cube). After copying a square (with dimensions width x depth), we continue with a cube, travelling along its height, or j axis. Lastly, we check that the travel direction corresponds to the remaining axis: after finishing a cube, we go to the next cube, which is indeed along h. This gives a an index order (minor to major) of k, i, j, h.
The formulae for u and v come straight from the T[M][N] to T[M*N] conversion. Each index of arrayConvt uses two indices from the hypercube, in the previously determined index order: that's h and j for u, and i and k for v. Thus, u = h * 3 + j and v = i * 3 + k.
int M = 3,
N = 3,
P = 3,
Q = 3;
for (int h = 0; h < M; ++h) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < P; ++j) {
for (int k = 0; k < Q; ++j) {
arrayConvt[h * 3 + j][i * 3 + k] = array[h * 3 + i][j][k];
}
}
}
}
Note the index expressions here can be converted to the ones used earlier. You could use this to write a non-nested loop over 0..80 that reshapes array, but it wouldn't be as readable. You can also use this approach to reshape the hypercube to any compatible shape you want.
I am working on a game in Java and I need to cache some position-based information. If I have the following array:
int[][] array = {
{1, 2, 3},
{1, 2, 3},
{1, 2, 3}
};
And then I have this other array:
int[][] otherArray = {
{4, 5, 6},
{4, 5, 6},
{4, 5, 6}
};
Now I want to combine them in a special way. I want to add otherArray to the left of array. So the result would look like this:
int[][] combinedArray = {
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3}
};
Then I have this other combined array:
int[][] otherCombinedArray = {
{30, 17, 139, 65, 335, 99},
{50, 43, 57, 53, 423, 534},
{90, 67, 78, 24, 99, 67}
};
Now I want to add it to the top of the original combined array. So the final result would look like this:
int[][] finalCombinedArray = {
{30, 17, 139, 65, 335, 99},
{50, 43, 57, 53, 423, 534},
{90, 67, 78, 24, 99, 67},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3},
{4, 5, 6, 1, 2, 3}
};
Can someone point me to a good library or built in method for doing this? I also wanted to note that the method shouldn't be too computationally heavy (like looping through all the arrays multiple times, and it shouldn't use too much memory, like 80MB).
Thank you for the help!
On it's own, Java does not provide concatenation methods, but we can use System.arraycopy (as suggested by #user16320675 above)
With System.arraycopy you specify the array to copy + the destination array -> you have array A of size 10 and B of size 2, and you use the command to copy your B array into A.
int[] source = { 1,2,3,4,5 };
int[] destination = new int[10];
// You can play with the numbers below
int COPY_AT_INDEX = 0; // Start to copy at position destination[0]
int AMOUNT_TO_COPY = 5; // Copying from 0 to source.length
System.arraycopy(source, 0, destination, COPY_AT_INDEX, AMOUNT_TO_COPY);
System.out.println(Arrays.toString(source)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(destination)); // [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
Now, if we use arraycopy, seems you have to determine when to copy as rows, and when to copy as columns.
// Assuming a[][] and b[][] have the same size.
public int[][] mergeAsColumns(int[][] a, int[][] b) {
int rows = a.length;
int columns = a[0].length;
int[][] merged = new int[rows][2 * columns];
for (int i = 0; i < a.length; i++) {
System.arraycopy(a[i], 0, merged[i], 0, columns);
System.arraycopy(b[i], 0, merged[i], rows, columns);
}
return merged;
}
Merging as Rows is similar to the other one, but changes in which positions you want to affect and how you create the merged array.
// Assuming a[][] and b[][] have the same size.
public int[][] mergeAsRows(int[][] a, int[][] b) {
int rows = a.length;
int columns = a[0].length;
int[][] merged = new int[2 * rows][columns];
for (int i = 0; i < rows; i++) {
System.arraycopy(a[i], 0, merged[i], 0, columns);
System.arraycopy(b[i], 0, merged[rows + i], 0, columns);
}
return merged;
}
I have a question concerning Java. I started up new to Java and my google search brought many results but non was the final help.
I created a class to track historical information. I have different values for different days and need to update them un a regular basis. I want to keep track of the last 30 days and created an array with 30 elements. When I call my 'shift' function I want to drop the last n elements and put zeros in front. Here is a minial example for 5 days:
public class Testclass {
private int[] histInfo;
public Element()
{
this.histInfo = new int[5];
}
public void shift_histInfo(long m)
{
//do magic
}
}
What I want shift to do is
INPUT:
histInfo = [50,21,1,45,901]
OPERATION:
shift_histInfo(2);
RESULT:
histInfo = [0,0,50,21,1]
I am thankfull for every kind of help you can support as well for thought-provoking impulses if you think that there is a way more elegant or efficient way.
Best :-)
Unless there are very tight performance constraints using the standard Collection classes will get the job done. Have a look at java.util.LinkedList.
As a programming exercise you might consider creating a ring buffer. The idea being to avoid copying the array on every insertion.
Keep a oldestIndex value.
When writing simply replace item[oldestIndex] and increment oldestIndex.
To iterate you start at oldestIndex and use an increment method to deal with wrapping round to the start of the array.
int nextIndex(int current) {
return (current + 1) % arrayLength;
}
Writing a nice encapsulating class to hide all this would be a good exercise.
You can try this :
public static void shift_histInfo(long m)
{
int[] myIntArray = {50,21,1,45,901};
int[] myIntArray2 = {50,21,1,45,901};
for (int j=0 ;j< myIntArray.length ; j++){
int temp = (int) (j+m);
if (temp >= myIntArray.length){
temp = temp - myIntArray.length;
myIntArray2[temp] = 0;
} else {
myIntArray2[temp] = myIntArray[j];
}
}
for (int j=0 ;j< myIntArray2.length ; j++){
System.out.println(myIntArray2[j]);
}
}
Output :
when shift_histInfo(2) ,
[0,0,50,21,1]
int[] array={1,2,3,4,5,6};
int removelength=2;
int e=1;
while(e<=removelength) {
for(int i=1;i<array.length;i++)
array[array.length-i]=array[array.length-i-1];
e++;
}
for(int i=0;i<removelength;i++) {
array[i]=0;
}
for(int g:array)
{
System.out.print(g);
}
For constraints that you wanted, although I did initialise the data in the same method instead of Element(). I don't know why the parameter is of type long so I left it and made an int local variable.
All it does is copy the index value over to the new array starting at m then increments/iterates until the end of the array.
You can also make the method return type int[] and then simply return changedInfo array. Instead of histInfo = changedInfo.clone();
private int[] histInfo;
public void shift_histInfo(long m) {
int n = (int) m;
this.histInfo = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15};
int length = this.histInfo.length;
int[] changedInfo = new int[length];
if (length - n >= 0) System.arraycopy(histInfo, 0, changedInfo, n + 0, length - n); //Edit: shortened to one line.
histInfo = changedInfo.clone();
System.out.println("Remove: " + n + " - " + Arrays.toString(changedInfo) + "\n");
}
public static void main(String[] args) {
Main main = new Main();
main.shift_histInfo(0);
main.shift_histInfo(30);
main.shift_histInfo(1);
main.shift_histInfo(15);
main.shift_histInfo(29);
}
println:
Remove: 0 - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Remove: 30 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Remove: 1 - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Remove: 15 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Remove: 29 - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
I have a troubles with an application.
I would like to move my String into this ArrayList.
My String contains numbers like 15 17 18 110 113 (numbers from 1 do 200).
I have about 80 numbers in one String, eg.:
I/System.out: 15 13 13 12 12 11 11 21 21 39 39 38 38 40 40 41 41 42 42 43 43 74 74 75 75 76 76 77 77 78 78 80 80 99 99 100 100 102 102 103 103 105 105 104
While I have List<String> tmpPath = new ArrayList<>(); and I have tried two different methods:
1.
public void transferStringToArray(string s1){
for(int i = 0; i < s1.length(); i++){
int extra = 0;
if(s1.charAt(i) != ' '){
String x = Character.toString(s1.charAt(i));
tmpPath.add(extra, x);
else extra++;
}
}
where the output is:
I/System.out: [4, 0, 1, 5, 0, 1, 5, 0, 1, 3, 0, 1, 3, 0, 1, 2, 0, 1, 2, 0, 1, 0, 0, 1, 0, 0, 1, 9, 9, 9, 9, 0, 8, 0, 8, 8, 7, 8, 7, 7, 7, 7, 7, 6, 7, 6, 7, 5, 7, 5, 7, 4, 7, 4, 7, 3, 4, 3, 4, 2, 4, 2, 4, 1, 4, 1, 4, 0, 4, 0, 4, 8, 3, 8, 3, 9, 3, 9, 3, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 5, 1]
(numbers are printed from last to first number which is wrong with my assumptions)
2.
public void transferStringToArray(string s1){
for(int i = 0; i < s1.length(); i++)
if(s1.charAt(i) != ' '){
String x = Character.toString(s1.charAt(i));
tmpPath.add(x);
}
where the output is in good order, but one number means one index of an array.
I/System.out: [1, 5, 1, 3, 1, 3, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 3, 9, 3, 9, 3, 8, 3, 8, 4, 0, 4, 0, 4, 1, 4, 1, 4, 2, 4, 2, 4, 3, 4, 3, 7, 4, 7, 4, 7, 5, 7, 5, 7, 6, 7, 6, 7, 7, 7, 7, 7, 8, 7, 8, 8, 0, 8, 0, 9, 9, 9, 9, 1, 0, 0, 1, 0, 0, 1, 0, 2, 1, 0, 2, 1, 0, 3, 1, 0, 3, 1, 0, 5, 1, 0, 5, 1, 0, 4]
Do you have any ideas how to move full number as one index separated by a space?
Also I have one more question:
How could I delete all repeated numbers? I know, that numbers are printed once or twice but in the result I have to have unique numbers.
All you need to do is a split with space s.split("\\s+"), and then put the result in a Set like this:
Set<String> set = new HashSet<>(Arrays.asList(s.split("\\s+")));
Or if you want to maintain the order, you can use :
Set<String> set = new LinkedHashSet<>(Arrays.asList(s.split("\\s+")));
If you are looking to use List and nothing else, then you can use, distinct like so :
List<String> set = Arrays.stream(s.split("\\s+"))
.distinct()
.collect(Collectors.toList());
Outputs
[15, 13, 12, 11, 21, 39, 38, 40, 41, 42, 43, 74, 75, 76, 77, 78, 80, 99, 100, 102, 103, 105, 104]
To convert space separated string into an array list :
You first need to split your string into an string array and then convert it into array list
public void convertStringToList() {
String stringToSplit = "15 13 13 12";
String[] splittedString = stringToSplit.split(" "); // Will split string based upon the space into an string array
List<String> listOfStrings = Arrays.asList(splittedString);
}
To remove the duplicates, you can insert all the array lists value into a Set. A set is a data structure in java which stores only unique values.
Set<String> uniqueValuesSet = new HashSet<>(listOfStrings);
for(String str : uniqueValuesSet) {
System.out.println(str);
}
In 2nd point, you might see your output is in random order. That is because HashSet doesn't maintain order of elements. If you need to maintain order as well. Use LinkedHashSet.
Set<String> uniqueValuesSet = new LinkedHashSet<>(listOfStrings);
for(String str : uniqueValuesSet) {
System.out.println(str);
}
Note: This solution assumes number in the original string are single space separated. If you want solution irrespective of number of spaces between 2 numbers, replace this line in point 1
String[] splittedString = stringToSplit.split(" ");
To
String[] splittedString = stringToSplit.split("\\s+");
I'm sticking with Set, as MaciejB wanted to eliminate duplicates and that's the contract of Set.
And, as MaciejB mentioned order too, I parsed them as Integer & put 'em in a TreeSet.
That looks like this:
Set<Integer> set = Stream.of(s.split("\\s+")).map(Integer::parseInt).collect(Collectors.toCollection(TreeSet::new));
Or if you prefer multiple lines:
Set<Integer> set = Stream // Result is ordered, parsed Set
.of(s.split("\\s+")) // -> String[]
.map(Integer::parseInt) // -> Integer[] for order in TreeSet
.collect(Collectors.toCollection(TreeSet::new)); // no duplicates
Outputs:
[11, 12, 13, 15, 21, 38, 39, 40, 41, 42, 43, 74, 75, 76, 77, 78, 80, 99, 100, 102, 103, 104, 105]
I have a 2d array called interval[g][2] where g is some number.
Currently, I'm trying to sort the array first by increasing order in the first element, and if they are equal, sort by decreasing order in the second element.
I've attempted this in two ways:
1) Using Java 8's Comparator.comparing method:
Arrays.sort(interval, Comparator.comparing((int[] arr) -> arr[0]));
2) Using Arrays.sort:
Arrays.sort(interval, new Comparator<int[]>() {
#Override
public int compare(int[] s1, int[] s2) {
if (s1[0] > s2[0])
return 1;
else if (s1[0] < s2[0])
return -1;
else {
if(s1[1] < s2[1])
return 1;
else if (s1[1] > s2[1])
return -1;
else
return 0;
}
}
});
The first method returns a partially sorted list.
[[0, 10], [10, 30], [30, 50]]
[[0, 10], [3, 19], [35, 45]]
[[10, 30], [27, 33], [30, 50]]
[[-10, 10], [0, 20], [35, 45]]
[[10, 30], [20, 40], [30, 50]]
[[0, 20], [8, 28], [37, 43]]
[[0, 20], [15, 35], [37, 43]]
[[0, 0], [8, 28], [10, 40]]
As you can see, it's sorting things in a set of three tuples.
The second method doesn't sort the array at all. Can I not sort using primitive data types? Can anyone advise?
I think you're looking for this:
Arrays.sort(interval, Comparator.comparingInt((int[] arr) -> arr[0]).thenComparing(Comparator.comparingInt((int[] arr) -> arr[1]).reversed()));
Or if you want to go with the custom Comparator:
Arrays.sort(interval, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2) {
int result = Integer.compare(o1[0], o2[0]);
if (result == 0) {
result = Integer.compare(o2[1], o1[1]);
}
return result;
}
});
int[][] interval = new int[][] { {0, 10}, {10, 30}, {30, 50}, {0, 10}, {3, 19}, {35, 45}, {10, 30}, {27, 33}, {30, 50}, {-10, 10}, {0, 20}, {35, 45}, {10, 30}, {20, 40}, {30, 50}, {0, 20}, {8, 28}, {37, 43}, {0, 20}, {15, 35}, {37, 43}, {0, 0}, {8, 28}, {10, 40} };
Arrays.sort(interval, Comparator.<int[]>comparingInt(arr -> arr[0]).thenComparing(arr -> arr[1], Comparator.<Integer>naturalOrder().reversed()));
Stream.of(interval).forEachOrdered(ints -> System.out.println(Arrays.toString(ints)));