How disable changing variable inside array? [duplicate] - java

This question already has answers here:
Problem with assigning an array to other array in Java
(4 answers)
Closed 4 years ago.
I have 2D array:
int[] zero = {
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1};
int[][] tab = {zero, zero};
I want to change this:
tab[0][0] = 0;
But when I did that It also change tab[1][0]. Can you tell me how can I disable that?

By making it so the two arrays are different objects rather than the same object.
One way to achieve that would be:
int[][] tab = {zero.clone(), zero.clone()};

Related

What is the most efficient way to create a 2d string array of initally repetitive data?

In Python, typically to define said game board I would have used the following code:
board = [['0','0','0','0','0','0','0','0','0','0'] for i in range(10)]
However, using Java the only way I have been able to find so far to produce the same result would be to do:
public static String[][] board = {
{"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"},
{"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"},
{"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"},
{"0","0","0","0","0","0","0","0","0","0"}};
Surely there must be a more efficient way of doing this. I know I can do it efficiently if it were to be integers, but it has to be strings given the situation. I had thought a for loop would also have applied, but I can't seem to find the right syntax for it; perhaps it isn't applicable for Java. Are there any suggestions?
You can loop over each row and use Arrays.fill:
public static String[][] board = new String[rows][cols];
static {
for (String[] row : board) Arrays.fill(row, "0");
}
Demo
You can use nested for loops to create the 10 rows and 10 columns. So within the first loop (which creates a "row"), you'd add another loop to fill the "columns."
String[][] board = new String[10][10];
// 10 rows
for (int i = 0; i < 10; i++) {
// 10 columns
for (int j = 0; j < 10; j++) {
// Set the value of this row/column
board[i][j] = "0";
}
}
This obviously isn't as elegant as Python's one-line solution, but it does what you need.
There are other ways to do this (such as just adding a full 10-digit array to the board array in each loop), but I find this to be best for scalability and readability.
For further clarity, if you may possibly need to change the number of rows or columns in the future, it would be better to move those values to variables and use those instead:
int rows = 10;
int cols = 10;
String[][] board = new String[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; i++) {
board[i][j] = "0";
}
}
This way you only need to update the variables instead of also modifying the for loops and array declaration.
You can do it like this. Since Strings are immutable, it's safe to use clone() here. Thanks to #iota for suggesting setAll
int n = 10;
String[][] arr = new String[n][n];
Arrays.fill(arr[0], "0");
Arrays.setAll(arr, i->arr[0].clone());
for(String[] a : arr) {
System.out.println(Arrays.toString(a));
}
Prints
[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]
[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]
[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]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
The following is a stream-based solution to the problem that uses a functional style, rather than an iterative style:
return Stream.generate(() ->
Collections.nCopies(10, "0").toArray(String[]::new))
.limit(10)
.toArray(String[][]::new);
Note that depending on the readability, etc. requirements, a classic iterative style may be deemed more desirable.
Explanation
Collections.nCopies(10, "0") creates a List<String> of 10 "0" values. This is converted to a String array using Collection.toArray(IntFunction). This takes an IntFunction which generates an array of a given length. String[]::new is a constructor lambda which implements IntFunction<String[]>, creating an array of the given length.
Stream.generate creates an infinite stream with each element created by a call to a given Supplier. In this case, the supplier creates the aforementioned 10-element long list, resulting in a Stream<String[]>. A generator is used, rather than Collections.nCopies, since each String[] in the String[][] needs be a different object.
The infinite stream is limited to just ten elements using Stream.limit(10).
Finally, the Stream<String[]> is collected into a String[][] by using Stream.toArray(IntFunction), which works in the same manner as the Collection.toArray method already described.
This is a hybrid of for loop and manually creating one row of cells.
String[][] board = new String[10][];
for (int i = 0; i < 10; i++) {
board[i] = new String[]{"0","0","0","0","0","0","0","0","0","0"};
}
String#repeat since 11
String[][] board = new String[10][];
Arrays.setAll - for each row repeat 0 ten times and split into an array:
Arrays.setAll(board, i -> "0".repeat(10).split(""));
Arrays.fill - in this case, the result is the same:
Arrays.fill(board, "0".repeat(10).split(""));
Output:
Arrays.stream(board).map(Arrays::toString).forEach(System.out::println);
[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]
[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]
[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]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
See also: How can I fill this 2D array with X characters?

Java adding a 2D arraylist to a list of 2D arraylists

I am creating a map system for my game which requires me at a few stages to replace the old 2D array map with another. What I wanted to do is add all the 2D arraylist maps into a List of these 2D arraylists. However, what I found difficult was that when I wanted to retrieve said map, the .get method would not give me the correct data, as it you would try to pull the first item of that arraylist which in this case would be null. Thus the program threw me nullpointerexceptions.
private int[][] mapArray;
private List<int[][]> maps = new ArrayList<>();
mapArray = new int[][]{
{0, 0, 1, 3, 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, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0},
{0, 1, 9, 1, 1, 7, 7, 7, 7, 1, 1, 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},
{7, 7, 7, 7, 5, 8, 8, 8, 4, 6, 1, 1, 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},
{4, 4, 4, 4, 4, 8, 8, 8, 4, 4, 6, 7, 7, 1, 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},
{4, 4, 4, 4, 4, 8, 8, 8, 4, 4, 4, 4, 4, 1, 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}
};
maps.add(mapArray);
When I sout maps.get(0) I get the following:
[[I#58838f3f
If I have two items, it will show up like this:
[[[I#58838f3f, [[I#59a60155]
Ideally I want it to be added like this:
[I#58838f3f, I#58838f3f]
I am just unsure how to do this. Any help would be appreciated!
I might have overlooked something obvious, probably is the case!
Much obliged
You seem to be confusing the output of converting your map (or the list of maps) to string (which is what happens when you try to print them) - with what actual value there are there.
Because ArrayList like most Java container formats have nice toString() implementations that get automatically called when trying to print them, you'd get something that "looks like an array" in the output. So for example when printing an array list containing two strings, it might look like this: [a, b].
Arrays don't have such nice formatters, because they aren't really objects (they are "primitive types") and so print them gets you their address and some Java byte code that describes their type (if you can understand Java byte code), so an array of integers will look like this: [I#<address> while an two dimensional array of bytes will look like this: [[B#<address>, and so on.
In regards to your original question, the code seems to work well for me. Here is an example program:
import java.util.ArrayList;
public class Test2D {
public static void main(String... args) {
ArrayList<int[][]> maps = new ArrayList<>();
maps.add(new int[][] {
{1,2,3},
{4,5,6},
{7,8,9},
});
maps.add(new int[][] {
{10,20,30},
{40,50,60},
});
int[][] map = maps.get(0);
System.out.println(map[0][0]);
}
}
The output will print correctly 1 , showing that there is no null pointer exception.

Convert Binary Array to Char Java

I have this binary array:
int[] bitArray = {
0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,
0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,1,1,
0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,
0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,
0,1,1,1,1,0,0,1,};
It makes the phrase: The sun is in the sky
How would you convert the int binary array to a char?
Every eight bits make up a char. You could just loop over the bits and accumulate every eight together:
int[] bitArray = {0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1,};
char[] chars = new char[bitArray.length / 8];
for (int i = 0; i < chars.length; ++i) {
int c = 0;
for (int j = i * 8; j < (i + 1) * 8; ++j) {
c = c << 1;
c += bitArray[j];
}
chars[i] = (char)c;
}
String s = new String(chars);
System.out.println(s);
Loop over every byte (8 bits) of the array, create a string of those bits, and then convert those bits to an integer using Integer.parseInt(x,2) and then cast that to a character and added to the result.
public static void main (String[] args) throws java.lang.Exception
{
int[] bitArray = {0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,0,1,1,1,1,0,0,1,};
int CHAR_SIZE = 8;
String T = "";
String result ="";
for (int i=0; i<bitArray.length; i+= CHAR_SIZE)
{
for (int j=0; j<CHAR_SIZE; j++)
T += Integer.toString(bitArray[i+j]);
result += Character.toString((char)Integer.parseInt(T, 2));
T="";
}
System.out.println(result);
}
output
The sun is in the sky
ASCII chars are one byte. One byte is eight bits. Separate the array elements in segments of 8 (0-7), (8-15), ...
Store these segments in another array. Use the following constructor to finish.
public String(byte[] bytes,
Charset charset)
Remember to specify utf8 as your charset. This causes the chars to be treated as one-byte ASCII chars.

extract string component to store as hash map key within function, pattern matcher?

I have data stored in files at paths such as:
/home/yamada/data/train/atheism/file_name.txt
I use this data to populate a hash map, storing the origin of the data and its contents as follows.
/home/yamada/data/test/sports/t.s_1.txt, [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0]
/home/yamada/data/test/politics/t.p_0.txt, [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
/home/yamada/data/test/atheism/t.a_0.txt, [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
/home/yamada/data/test/science/t.s_0.txt, [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0]
However, I want only to store the path to the point of the directory, not the specific file, like so:
/home/yamada/data/train/atheism
The following regex command is capable of extracting the component I'm interested in according to regex101.com:
(home\/yamada\/data\/train\/atheism)
How could I use the java pattern matcher to ensure that only the string mentioned earlier, the path up to and including the directory, but not the file name, is saved to the hash map?
Is the pattern matcher the best choice for this operation?
Below is the method that populates the hash map.
public static void perceptron_data_struc_generateur(Set<String> GLOBO_DICT,
Map<File, ArrayList<String> > fileDict,
Map<File, int[] > perceptron_input)
{
//create a new entry in the array list 'perceptron_input'
//with the key as the file name from fileDict
//create a new array which is the length of GLOBO_DICT
//iterate through the indicies of GLOBO_DICT
//for all words in globo dict, if that word appears in fileDict,
//increment the perceptron_input index that corresponds to that
//word in GLOBO_DICT by the number of times that word appears in fileDict
//so i can get the index later
List<String> GLOBO_DICT_list = new ArrayList<>(GLOBO_DICT);
for (Map.Entry<File, ArrayList<String>> entry : fileDict.entrySet())
{
int[] cross_czech = new int[GLOBO_DICT_list.size()];
//initialize to zero
Arrays.fill(cross_czech, 0);
for (String s : GLOBO_DICT_list)
{
for(String st : entry.getValue())
{
if( st.equals(s) )
{
cross_czech[ GLOBO_DICT_list.indexOf( s ) ] = cross_czech[ GLOBO_DICT_list.indexOf( s ) ] +1;
}
}
}
perceptron_input.put( entry.getKey() , cross_czech);
}
}
It's quite a bit simpler than that:
String dir = filename.replaceAll("/[^/]*$", "");
If I understand your question correctly you want to find only parts which ends with / (file name will not have it). In that case
(\w+/)+
should do the trick (BTW we don't escape / in Java's regex)
But if your data is always in form path/to/file and you only want to extract path/to then you don't need regex, you can use File class and its getParent method like
String data = new File("/home/yamada/data/train/atheism/file_name.txt").getParent();
System.out.println(data);
This will return \home\yamada\data\train\atheism so you will have / instead of \, but this shouldn't be a problem if you want to use this data in Java (File accepts both separators).

Android java assigning 2d array to 3d array

I'm running into problems trying to assign a 2d array to a 3d array, so I thought i'd ask a question about 3d and 2d arrays.
Say I have a masterArray[][][] and wanted to put childArray1[][] and childArray2[][] into it.
This is how I have done it and was wondering if that is the correct way of applying it:
private int[][][] masterArray;
private int[][] childArray1 = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 0, 0, 1, 0, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 1, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 1, 1, 0, 1, 8, 1, 0, 1},
{1, 0, 7, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 9, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
private int[][] childArray2 = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
{1, 1, 1, 1, 7, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 0, 0, 1, 1, 1},
{1, 1, 1, 9, 1, 1, 8, 0, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
Ok, so in my init method I use these some methods to set the child arrays into the master array. What I was curious about was how this exactly works. I assumed the following:
masterLevel = new int[MAX_LEVELS][MAP_WIDTH][MAP_HEIGHT];
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
masterArray[currentLevel][x][y] = childArray1[x][y];
}
}
Would that work?
In my application things aren't working so I picking out code that I am not 100% sure on.
It doesn't really matter how you organize a 3d array as long as you put things in the same way as you take them out.
From your comment on another answer it seems that you are having problem with element order ([currentLevel][x][y] = childArray[y][x];)
It seems you mixed MAP_HEIGHT and MAP_WIDTH. It should be:
masterLevel = new int[MAX_LEVELS][MAP_HEIGHT][MAP_WIDTH];
then you can use:
master[currentLevel][x][y] = childArray[x][y];
In Java multi-d arrays are actually arrays of arrays. So they can even be disjoint.
In the code you posted you refer to a variable called currentLevel that you did not define. I am sure that is defined in some code you did not post. Also don't forget that arrays are zero index. This code should work.
masterArray = new int[MAX_LEVELS][MAP_WIDTH][MAP_HEIGHT];
for (int currentLevel = 0; currentLevel < MAX_LEVELS; currentLevel++) {
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
masterArray[currentLevel][x][y] = childArray1[x][y];
}
}
}
If you ever work with massive arrays and need speed then you could look at System.arrayCopy();
String[] arr1D;
String[][] arr2D;
String[][][] arr3D;
arr1D = new String[] { "1", "2", "3" };
//////////////////////////////////////////////////////////////////////////
//assign 1D array to element of 2D array
//////////////////////////////////////////////////////////////////////////
arr2D = new String[][] {
arr1D ,
arr1D ,
arr1D
};
/*
// OR
arr2D = new String[3][];
arr2D[0] = arr1D;
arr2D[1] = arr1D;
arr2D[2] = arr1D;
// OR
arr2D = new String[][] {
new String[] { "1", "2", "3" } ,
new String[] { "1", "2", "3" } ,
new String[] { "1", "2", "3" }
};
*/
//////////////////////////////////////////////////////////////////////////
//assign 2D array to element of 3D array
//////////////////////////////////////////////////////////////////////////
arr3D = new String[][][] {
arr2D ,
arr2D ,
arr2D
};
/*
// OR
arr3D = new String[3][][];
arr3D[0] = arr2D;
arr3D[1] = arr2D;
arr3D[2] = arr2D;
*/

Categories