I'm quite new to Java, but getting into it. However, I can't wrap my head around why this example, which I found here, does not work:
At start of class:
String[][] spritesPaint = new String[20][20];
In method:
for (int funct1 = 0; funct1 <= 2; funct1++) {
if (funct1 == 0) {
for (int funct2 = 0; funct2 < rEnemyNumber; funct2++) {
spritesPaint[0][funct2] = new Integer(rEnemyY[funct2])
.toString();
spritesPaint[1][funct2] = rEnemyGraphic[funct2];
}
} else if (funct1 == 1) {
Arrays.sort(Integer.valueOf(spritesPaint[0].toString()),
new Comparator<Integer[]>() {
#Override
public int compare(final Integer[] entry1,
final Integer[] entry2) {
final Integer time1 = entry1[0];
final Integer time2 = entry2[0];
return time1.compareTo(time2);
}
});
} else if (funct1 == 2) {
for (int funct3 = 0; funct3 < rEnemyNumber; funct3++) {
if (rEnemyCheck[funct3] == true) {
nextPaint = getImage(base, rEnemyGraphic[funct3]);
System.out.println("Next: " + nextPaint);
g.drawImage(nextPaint, rEnemyX[funct3] + worldCenterX,
rEnemyY[funct3] + worldCenterY, this);
}
}
}
}
Basically, what I want to do is have a two dimensional array where I store Y position of object on the screen and an image path also related to that object, then sort it by the Y position integer. This should allow me to paint elements to the screen in the correct order for an isometric perspective.
However, I keep getting this error:
The method sort(T[], Comparator<? super T>) in the type Arrays
is not applicable for the arguments (Integer, new Comparator<Integer[]>(){})
Please help me, I've been twisting my brain for hours trying to understand why I get this error now.
Integer.valueOf(spritesPaint[0].toString()) is a single integer, however from your description it seems that you want to sort the strings in the 1-dimensional array spritesPaint[0] as if they were integers. Here is a modification that will do just that:
Arrays.sort(spritesPaint[0], new Comparator<String>() {
#Override public int compare(final String entry1, final String entry2) {
final Integer time1 = Integer.valueOf(entry1);
final Integer time2 = Integer.valueOf(entry2);
return time1.compareTo(time2);
}
});
Alternatively, if you are trying to sort the first dimension of the array by the first element of the second dimension of the array, modify as follows:
Arrays.sort(spritesPaint, new Comparator<String[]>() {
#Override public int compare(final String[] entry1, final String[] entry2) {
final Integer time1 = Integer.valueOf(entry1[0]);
final Integer time2 = Integer.valueOf(entry2[0]);
return time1.compareTo(time2);
}
});
The error message means that, instead of passing an Array of type T (generic), you are passing an Integer. So, where you have:
Arrays.sort(Integer.valueOf(spritesPaint[0].toString()), ...
you want to pass in
Arrays.sort(arrayToBeSorted, ...
(Also, your variables could do with better names because I really don't understand what this example is doing...)
Related
I read Bert Bates and Katie Sierra's book Java and have a problem.
The Task: to make the game "Battleship" with 3 classes via using ArrayList.
Error: the method setLocationCells(ArrayList < String >) in the type
SimpleDotCom is not applicable for the arguments (int[])
I understand that ArrayList only will hold objects and never primatives. So handing over the list of locations (which are int's) to the ArrayList won't work because they are primatives. But how can I fix it?
Code:
public class SimpleDotComTestDrive {
public static void main(String[] args) {
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
int randomNum = (int) (Math.random() * 5);
int[] locations = {randomNum, randomNum+1, randomNum+2};
theDotCom.setLocationCells(locations);
boolean isAlive = true;
while(isAlive) {
String guess = helper.getUserInput("Enter the number");
String result = theDotCom.checkYourself(guess);
numOfGuesses++;
if (result.equals("Kill")) {
isAlive = false;
System.out.println("You took " + numOfGuesses + " guesses");
}
}
}
}
public class SimpleDotCom {
private ArrayList<String> locationCells;
public void setLocationCells(ArrayList<String> loc) {
locationCells = loc;
}
public String checkYourself(String stringGuess) {
String result = "Miss";
int index = locationCells.indexOf(stringGuess);
if (index >= 0) {
locationCells.remove(index);
if(locationCells.isEmpty()) {
result = "Kill";
} else {
result = "Hit";
}
}
return result;
}
}
public class GameHelper {
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0)
return null;
} catch (IOException e) {
System.out.println("IOException:" + e);
}
return inputLine;
}
}
convert ArrayList to int[] in Java
Reason for Basic Solution
Here's a simple example of converting ArrayList<String> to int[] in Java. I think it's better to give you an example not specific to your question, so you can observe the concept and learn.
Step by Step
If we have an ArrayList<String> defined below
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
Then the easiest solution for a beginner would be to loop through each list item and add to a new array. This is because the elements of the list are type String, but you need type int.
We start by creating a new array of the same size as the List
int[] numbers = new int[numbersInAList.size()];
We then iterate through the list
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
Then inside the loop we start by casting the String to int
int num = Integer.parseInt(numbersInAList.get(ndx));
But there's a problem. We don't always know the String will contain a numeric value. Integer.parseInt throws an exception for this reason, so we need to handle this case. For our example we'll just print a message and skip the value.
try {
int num = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
We want this new num to be placed in an array, so we'll place it inside the array we defined
numbers[ndx] = num;
or combine the last two steps
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
Final Result
If we combine all of the code from "Step by Step", we get the following
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
int[] numbers = new int[numbersInAList.size()];
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
try {
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
}
Important Considerations
Note there are more elegant solutions, such as using Java 8 streams. Also, it's typically discouraged to store ints as Strings, but it can happen, such as reading input.
I can't see where you call setLocationCells(ArrayList<String>) in your code, but if the only problem is storing integers into an ArrayList there is a solution:
ArrayList<Integer> myArray = new ArrayList<Integer>();
myArray.add(1);
myArray.add(2);
It is true that you can't use primitive types as generics, but you can use the Java wrapper types (in this case, java.lang.Integer).
Let's assume I want to have a function, in which I will sort any array's first column using Comparator. I want to pass into that function multiple dimensions array, however, each time number of this dimensions can be different. I was thinking about using generic type function, however this approach doesn't seem to work. How to do it?
UPDATE:
I was thinking about writing code like this, but this doesn't even compile, and I am not quite sure how else could I do it. I must add, that I am only considering String arrays.
public <T> T sortArray(T array){
Arrays.sort(array, new Comparator<T>() {
#Override
public int compare(T lhs, T rhs) {
final String str1 = lhs[0];
final String str2 = rhs[0];
return str1.compareTo(str2);
}
});
return array;
}
You may need to change this if you want it to work for generics, but the following code will work for Objects in general (but change the casting in the compare method to cast to whatever type you pass in).
public Object[][] sortArray(Object[][] array){
Object[] columnElements = new Object[array.length];
for (int i = 0; i < array.length; i++) {
columnElements[i] = array[i][0];
}
Arrays.sort(columnElements, new Comparator<Object>() {
#Override
public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2);
}
});
for (int i = 0; i < array.length; i++) {
array[i][0] = columnElements[i];
}
return array;
}
I have an ArrayList in Java :
{"PatMic", "PatientDoc", "Phram", "Patnet", "PatientA"}
All the elements have a number assigned : PatMic = 20, PatientDoc = 30, Phram = 40, Patnet = 50, PatientA = 60.
And my current Comparator :
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(final String o1, final String o2) {
final int numbr1 = getElementNumber(); //Returns element's number in a list
final int numbr2 = getElementNumber();
if (numbr1 > numbr2 ) {
return 1;
} else if (numbr1 < numbr2 ) {
return -1;
}
return 0;
}
};
Collections.sort(strings, comparator);
I do not want to change the assigned numbers to each element but would want to move the element PatientA in between PatMic and PatientDoc so the modified list should look like :
{"PatMic", "PatientA" "PatientDoc", "Phram", "Patnet"}
Could someone please suggest how to achieve this? I tried many ways to modify the existing Comparator logic but in vain. Thank you.
You are trying to sort based on some inherent value associated with a String. Therefore, sorting on a String itself is probably not correct. What you probably want to use is either a custom object (implement equals, hashCode and the interface Comparable), or an enum type. This will allow you to change the internal state of these objects explicitly, which will manifest itself naturally when using a Comparator. For example, using a class:
class MyClass implements Comparable
{
private String name;
private int value;
//Constructor
public MyClass(String s, int v)
{
name = s;
value = v;
}
//Getters and setters
//Implement comparing method
}
Then you can use these objects in place of your Strings:
//...
MyClass patMic = new MyClass("PatMic", 20);
// So on..
First, you should give you comparator sufficient knowledge about what it should do. I mean you should have some data available to comparator that says something like "okay, sort them all by associated number except this one - place it right here". "Right here" could be anything that points exact position, I gonna choose "before that element".
So here we go
public void sortWithException(List<String> data, final Map<String, Integer> numbers, final String element, final String next) {
Collections.sort(data, new Comparator<String>() {
#Override
public int compare(String first, String second) {
if (first.equals(element) || second.equals(element)) { //the exception
Integer nextNumber = numbers.get(next);
Integer firstNumber = numbers.get(first);
Integer secondNumber = numbers.get(second);
if (first.equals(element)) {
if (next == null) // placing the exception after ANY element
return 1;
return secondNumber >= nextNumber ? -1 : 1; //placing the element before next and after all next's predecessors
} else { // second.equals(element)
if (next == null)
return -1;
return firstNumber >= nextNumber ? 1 : -1;
}
} else { //normal sort
return numbers.get(first) - numbers.get(second);
}
}
});
}
and call it like sortWithException(data, numbers, "PatientA", "PatientDoc")
Note that i used Map for associated numbers, you should probably use your own method to get those numbers.
Say I have an array of strings:
String[] array = {
"2183417234 somerandomtexthere",
"1234123656 somemorerandomtexthere",
"1093241066 andevenmore",
"1243981234 you get what i mean",
//etc
};
How would I sort this array using the long (it's a long) at the start of the string, so it'll end up looking like this:
String[] array = {
"1093241066 andevenmore",
"1234123656 somemorerandomtexthere",
"1243981234 you get what i mean",
"2183417234 somerandomtexthere",
//etc
};
I've tried everyting from making it an arraylist and using Collections#sort to creating my own comparator, to using a sorted map / tree map and I just can't figure it out.
Thanks.
Use this function:
static long comparedValue(String s) {
return Long.valueOf(s.substring(0, s.indexOf(' ')));
}
and then define a Comparator in terms of it:
public int compare(String left, String right) {
return comparedValue(left) - comparedValue(right);
}
Using Google Guava:
List<String> unsorted = Arrays.asList(array);
Function<String, Long> longFunction = new Function<String, Long>() {
#Override public Long apply(String input) {
return Long.valueOf(input.split(" ")[0]);
}
};
List<String> sorted = Ordering.natural().onResultOf(longFunction).immutableSortedCopy(unsorted);
Or if you don't wanna use a List (you should always prefer collections to arrays):
Arrays.sort(array, Ordering.natural().onResultOf(longFunction));
The input that you have shown works perfectly fine. But that's because all of them have the same number of digits.
public static void main(String[] args) {
String[] array = { "2183417234 somerandomtexthere",
"1234123656 somemorerandomtexthere", "1093241066 andevenmore",
"1243981234 you get what i mean", "999 little shorter"
// etc
};
List<String> list = Arrays.asList(array);
Collections.sort(list);
System.out.println(list);
}
Problems start to occur, when you use some shorter numbers - as 999 shown above...
output will be:
[1093241066 andevenmore, 1234123656 somemorerandomtexthere, 1243981234 you get what i mean, 2183417234 somerandomtexthere, 999 little shorter]
So, to make it working allways - you need your custom comparator, that will be able to split given Strings, and then take the number part out of them, and compare them. Using #Marko Topolik solution:
static long comparedValue(String s) {
return Long.valueOf(s.substring(0, s.indexOf(' ')));
}
public int compare(String left, String right) {
long result = comparedValue(left) - comparedValue(right);
boolean numberPartAreEqual = result == 0;
if (numberPartAreEqual) {
result = left.compareTo(right);
}
return (int) result;
}
A custom comparator should work fine:
public class LongPrefixComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
final long pref1 = getPrefixValue(s1);
final long pref2 = getPrefixValue(s2);
return s1 == s2 ? 0 : s1 < s2 ? -1 : 1;
}
private static long getPrefixValue(String stg) {
int len = stg.indexOf(' ');
if (len > 0) {
try {
return Long.parseLong(stg.substring(0, len));
catch (NumberFormatException ignored) {}
}
return 0L;
}
}
I have a simple question ?
String[] names = null ;
names[0] = "Hello"
I'm getting an error ..
How could I instantiate array as I don't know the the size limit... help me
Use ArrayList<String> when you don't know in advance the array size. What you are doing here is invalid (trying to access a null object).
Edit: as you can't use Vector and ArrayList, you'll have to roll you own implementation of dynamic array. You'll find one almost ready with some explanations on algolist.net. Simply replace the int storage by a String storage.
// Warning: not tested!
public class DynamicStringArray {
private String[] storage;
private int size;
public DynamicArray() {
storage = new String[10];
size = 0;
}
public DynamicArray(int capacity) {
storage = new String[capacity];
size = 0;
}
public void ensureCapacity(int minCapacity) {
int capacity = storage.length;
if (minCapacity > capacity) {
int newCapacity = (capacity * 3) / 2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
storage = Arrays.copyOf(storage, newCapacity);
}
}
private void pack() {
int capacity = storage.length;
if (size <= capacity / 2) {
int newCapacity = (size * 3) / 2 + 1;
storage = Arrays.copyOf(storage, newCapacity);
}
}
public void trim() {
int newCapacity = size;
storage = Arrays.copyOf(storage, newCapacity);
}
//...
}
How about this?
String[] names = new String[] { "Hello" };
Or you might also use ArrayList or StringCollection.
EDIT:
For J2ME: There was a trick posted here for dynamic array of Ints. I suppose it should possible to convert it for Strings. I have converted that example, however I didn't have J2ME emulator to test it:
public class DynamicStringArray {
private static final int CAPACITY_INCREMENT = 10;
private static final int INITIAL_CAPACITY = 10;
private final int capacityIncrement;
public int length = 0;
public String[] array;
public DynamicStringArray(int initialCapacity, int capacityIncrement) {
this.capacityIncrement = capacityIncrement;
this.array = new String[initialCapacity];
}
public DynamicStringArray() {
this(CAPACITY_INCREMENT, INITIAL_CAPACITY);
}
public int append(String str) {
final int offset = length;
if (offset == array.length) {
String[] old = array;
array = new String[offset + capacityIncrement];
System.arraycopy(old, 0, array, 0, offset);
}
array[length++] = str;
return offset;
}
public void removeElementAt(int offset) {
if (offset >= length) {
throw new ArrayIndexOutOfBoundsException("offset too big");
}
if (offset < length) {
System.arraycopy(array, offset + 1, array, offset, length - offset
- 1);
length--;
}
}
}
try
String[] names = new String[1];
names[0] = "Hello";
Use an ArrayList<String> if you don't know the size beforehand.
ArrayList<String> names = new ArrayList<String>();
names.add("hello");
names.add("another string");
...
looks like j2me has non-generic ArrayList that you could use like this.
ArrayList names = new ArrayList();
names.add("hello");
names.add("another string");
....
String name = (String) names.get(1);
How could i instantiate array as I dont know the the size limit
Sorry, that cannot be done. Arrays are of fixed size in Java, and you have to give the size when you create the array.
If you need a flexible buffer, consider using an ArrayList instead. That will grow as needed.
If you don't know the size limit (or more generally: almost always) you'll want to use a List instead of an array, because it's much more comfortable to handle.
List<String> names = new ArrayList<String>();
names.add("Hello");
The reason you're getting an exception (a NullPointerException) is that you only defined a variable to reference a String-array, but created no String array.
You'd have to initialize it like this:
String[] names = new String[10];
As you explained yo want to use it at J2ME there is no ArrayList provided for J2ME however there is an implementation here:
http://kickjava.com/src/j2me/util/ArrayList.java.htm
You can try it.
Also you should consider here too:
http://www1.j2mepolish.org/javadoc/j2me/de/enough/polish/util/ArrayList.html
As you are on J2ME and say you can't use arraylist I don't see you having any choice.
You need to choose a reasonable starting size for your array, watch the size, and if you need to add more objects than the size, copy it to a larger array.
With our constraints I cannot think of another way.
you can use with vector
Vector strings=new Vector();
strings.addElement("HELLO");
//then convert it to string array
String str[]=new String[strings.size()];
str[0]=(String)strings.get(0);
like this..
Hope this helpfull
String str[] = { "ABCde","xyZ","sdsdsdf"} ;
String str[][] = { {"ABC","abc"} ,
{"pqr","qwerTY"}
} ;