I was implementing Graph data structure in Java.
Here is my implementation:
package Graph;
import java.util.*;
import java.io.*;
public class Graphs
{
int size;
LinkedList<Integer>[] ll;
Graphs(int size)
{
this.size = size;
ll = new LinkedList[size];
for(int i=0; i<size; i++)
ll[i] = new LinkedList<Integer>();
}
public static void print(LinkedList lli)
{
for(Integer i: lli)
System.out.println(i);
//for(int i=0; i<lli.size(); i++)
// System.out.println(lli.get(i));
}
public static void addEdge(Graphs graph, int up, int to)
{
graph.ll[to].add(up);
}
public static void main(String args[])
{
int V=5;
Graphs graph = new Graphs(V);
addEdge(graph,1,2);
addEdge(graph,1,3);
addEdge(graph,2,3);
addEdge(graph,3,1);
addEdge(graph,3,2);
addEdge(graph,3,4);
addEdge(graph,4,3);
print(graph.ll[3]);
}
}
Basically I am creating an array of LinkedLists for the graph with each linked list for a vertex of the graph.
However, I am getting a java.lang.Object cannot be converted to java.lang.Integer at line number 24. Clueless as to why am I getting this error. Any suggestions as to what am I missing?
The specific issue you're having is with your print function:
public static void print(LinkedList lli){
for(Integer i: lli)
System.out.println(i);
}
LinkedList is a raw type, meaning you lose type information about what kinds of objects are stored in the list. As a general rule, raw types are a bad idea. I'm very surprised your code compiled, but suffice to say that by saying Integer i : lli you're assumming that every object within lli is an Integer when the parameter LinkedList provides no such guarantee.
To ensure that this will work, change LinkedList lli to LinkedList<Integer> lli. This means that every object in lli is an instance of Integer, thus the iteration won't fail.
When I try to run your code, my IDE warns me about the line
ll = new LinkedList[size]
Saying:
Unchecked assignment: 'java.util.LinkedList[]' to 'java.util.LinkedList< java.lang.Integer >[]'
Which indicates that something fishy is going on here.
Mixing Lists and Arrays gets a bit messy with generic typing - it's a lot easier and cleaner to just do lists of lists if you need size mutability, or a multi-dimension array if not. For your case, that argues for a ArrayList<LinkedList<Integer>> or the like.
We can fix the issues by resolving the generic issues:
import java.util.*;
import java.io.*;
public class Graphs
{
int size;
ArrayList<LinkedList<Integer>> ll;
Graphs(int size)
{
this.size = size;
ll = new ArrayList<LinkedList<Integer>>();
for(int i=0; i<size; i++)
ll.add(new LinkedList<Integer>());
}
public static void print(LinkedList<Integer> lli)
{
for(Integer i: lli)
System.out.println(i);
//for(int i=0; i<lli.size(); i++)
// System.out.println(lli.get(i));
}
public static void addEdge(Graphs graph, int up, int to)
{
graph.ll.get(to).add(up);
}
public static void main(String args[])
{
int V=5;
Graphs graph = new Graphs(V);
addEdge(graph,1,2);
addEdge(graph,1,3);
addEdge(graph,2,3);
addEdge(graph,3,1);
addEdge(graph,3,2);
addEdge(graph,3,4);
addEdge(graph,4,3);
print(graph.ll.get(3));
}
}
Declare the print method like this:
public static void print(LinkedList<Integer> lli)
Then it will know that the contents of lli are integers.
I copied your code and it didn't compile until I changed
public static void print(LinkedList lli)
to:
public static void print(LinkedList<Integer> lli)
From where it worked without problems
Also giving variables a name which starts with an upper case letter is against the naming convention. Have a look at this oracle tutorial. The last bullet point on the page states:
If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names gearRatio and currentGear are prime examples of this convention.
Related
I want a List of n Sets of Integers and initially this list should be filled with null.
A lot of the Sets will be initialised later, and some will remain null.
I have tried different methods to implement this, some of them are included here:
List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]);
ArrayList<HashSet<Integer>> List_of_Sets = new ArrayList<>(n);
while(n-- > 0) List_of_Sets.add(null);
Is there a faster way to do this?
For clarification an example for arrays would be Arrays.fill() used to be slower than:
/*
* initialize a smaller piece of the array and use the System.arraycopy
* call to fill in the rest of the array in an expanding binary fashion
*/
public static void bytefill(byte[] array, byte value) {
int len = array.length;
if (len > 0){
array[0] = value;
}
//Value of i will be [1, 2, 4, 8, 16, 32, ..., len]
for (int i = 1; i < len; i += i) {
System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i);
}
}
^above code is from Ross Drew's answer to Fastest way to set all values of an array?
Is there a faster way to do this?
As far as I am aware, no. Certainly, there is no easy way that is faster.
Based on how it works, I think (but I have not tested) that the Arrays.asList(new HashSet[n]) should be the fastest solution.
It would be possible to implement a custom List implementation that is like an ArrayList but is pre-initialized to N null values. But under the hood the initialization will be pretty much identical with what happens in the List implementation that asList returns. So I doubt that any performance improvements would be significant ... or worth the effort.
If you want to be sure of this, you could write a benchmark of the various options. However, I don't think this is the right approach in this case.
Instead I would recommend benchmarking and profiling your entire application to determine if operations on this list are a real performance hotspot.
If it is not a hotspot, my recommendation would be to just use the Arrays.asList approach and spend your time on something more important.
If it is a hotspot, you should consider replacing the List with an array. From your earlier description it seemed you are going to use the List like an array; i.e. using positional get and set operations, and no operations that change the list size. If that is the case, then using a real array should be more efficient. It saves memory, and avoids a level of indirection and (possibly) some bounds checking.
One reason not to do this would be if you needed to pass the array to some other code that requires a List.
If resizing is not important to you then implementing your own list might be fast. It might also be buggy. It would at least be interesting to benchmark compared to Java's lists. One strange effect that you might see is that standard lists might be optimised by the JIT sooner, as they could be used internally by Java's standard library.
Here is my attempt, although I suggest you don't use it. Use a standard list implementation instead.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
Set<Integer>[] arr = new Set[100_000]; // all set to null by default.
List<Set<Integer>> myList = new ArrayBackedList<>(arr);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class ArrayBackedList<T> extends AbstractList<T> {
private final T[] arr;
ArrayBackedList(T[] arr) {
this.arr = arr;
}
#Override
public T get(int index) {
return arr[index];
}
#Override
public int size() {
return arr.length;
}
#Override
public T set(int index, T value) {
T result = arr[index];
arr[index] = value;
return result;
}
}
Another possibility would be implementing an always-null, fixed-size list. Use that to initialise the ArrayList. I won't promise that it is fast but you could try it out.
import java.util.*;
public class FastListOfNullsDemo {
public static void main(String[] args) {
List<Set<Integer>> allNull = new NullList<>(100_000);
List<Set<Integer>> myList = new ArrayList<>(allNull);
myList.set(3, new TreeSet<Integer>());
myList.get(3).add(5);
myList.get(3).add(4);
myList.get(3).add(3);
myList.get(3).add(2);
myList.get(3).add(1);
System.out.println(myList.size());
// Let's just print some because 100,000 is a lot!
for (int i = 0; i < 10; i++) {
System.out.println(myList.get(i));
}
}
}
class NullList<T> extends AbstractList<T> {
private int count;
NullList(int count) {
this.count = count;
}
#Override
public T get(int index) {
return null;
}
#Override
public int size() {
return count;
}
}
The idea is if i am at a certain stair i can either go one step down or two so if am at stair 3 i can go down 1 1 1 or 2 1 for example. My code should print all the possibilities. The error I get is that I can't convert the add function to an array (since the add method is a boolean). What is wrong with this algorithm?
public class Stairs {
public static void staircase (int height ){
ArrayList<Integer> Array = null;
explore (height,Array);
}
public static void explore(int objheight,ArrayList<Integer>Array){
int intialheight = 0;
if (intialheight == objheight){
Array.toString();
}
else{ if (objheight > intialheight ){
explore(objheight-2,Array.add(2));
explore(objheight-1,Array.add(1));
}
}
after your feedback I am getting an empty output
import java.lang.reflect.Array;
import java.util.ArrayList;
public class Stairs {
public static void staircase (int height ){
ArrayList<Integer> Array = new ArrayList<Integer>();
explore (height,Array);
}
public static void explore(int objheight,ArrayList<Integer>Array){
int intialheight = 0;
if (intialheight == objheight){
Array.toString();
}
else{ if (objheight > intialheight ){
Array.add(2);
explore(objheight-2,Array);
Array.add(1);
explore(objheight-1,Array);
}
}}
public static void main (String args[]){
staircase(3);
}
}
The method add(E e) in ArrayList returns true upon appending the element e passed as a parameter to the end of the ArrayList.
Your method, explore(int objHeight, ArrayList<Integer> Array) does not accept a boolean for its second parameter. Yet, in that same method, explore, you are recursively calling explore and passing in a boolean to the method.
The following code should be modified to first invoke the add method of Array and then pass Array to the explore method.
Before:
explore(objheight-2,Array.add(2)); This code is passing parameters int and boolean to the explore method, which is not the parameters it accepts. You should instead attempt the following.
After:
Array.add(2);
explore(objheight-2,Array); This code first adds 2 to the Array and then passes the Array to the explore method without invoking any further methods on the Array object.
You will also need to do this for the next line of code, where you have explore(objheight-1,Array.add(1));.
Edit: Upon further examination of the code, I discovered another (sooner) error that occurs. A NullPointerException will occur each time the program runs:
ArrayList<Integer> Array = null;
explore (height,Array);
Then inside the explore method, different methods on Array are invoked, despite Array always being null:
Array.toString();, Array.add(2) and Array.add(1).
The Array object must be initialized inside of either the staircase or explore methods.
ArrayList<Integer> Array = new ArrayList<Integer>(); or ArrayList<Integer> Array = null;
Array = new ArrayList<Integer>();
I'm using a arraylist to add states(the board state for the 8 puzzle). My problem is when I get the children of the state it changes the values stored in my array list. I'm assuming this is because ArrayList just stores pointers to the objects and not the values themselves. In order to fix this I create a new object every time before I store it into the ArrayList but I'm still having the same problem.
I will also try to follow naming conventions more often thanks for the tip.
private ArrayList<int[][]>VisitedBoard;
if(RuleNumber ==2){
//Here is my problem. This will change what is stored in VistedBoards
NextState = new State(FireRule.Rule2(WM.get_Board()));//Fire Rule
for(int j=0;j<VisitedBoards.size();j++){
//Meaning this will always be true
if(Arrays.equals(VisitedBoards.get(j), NextState.get_Board())){
Loop =true; //Loop to previous state
}
if(j==VisitedBoards.size()-1 && Loop ==false){ //If the next state is not any previously visited
NotALoop =true;
VisitedBoards.add(NextState.get_Board());
WM.set_Board(NextState.get_Board());
}
}
}
public int[][] Rule2(int [][] Board){//The FireRule Class
Find_BlankLocation(Board);
int temp;
State NewState;
temp = Board[BlankLocation[0]-1][BlankLocation[1]];
Board[BlankLocation[0]-1][BlankLocation[1]] = 0;
Board[BlankLocation[0]][BlankLocation[1]] = temp;
NewState = new State(Board);
return Board;
}
public class State { //State class
private int[][] Board;
private int[][] Goal;
private Boolean GoalFound;
public State(int[][] Start, int[][] goal){
Board = Start;
Goal = goal;
GoalFound=false;
}
public State(int[][] NewState){
Board=NewState;
}
public int[][] get_Goal(){
return Goal;
}
public int[][] get_Board(){
return Board;
}
public void set_Board(int[][] board){
Board = board;
}
public Boolean get_GoalFound(){
return GoalFound;
}
}
Containers like ArrayList work the same in all languages: they are called data structures because they organize storage/retrieval of objects. Obviously they don't store the fields of the objects themselves.
Trying to interpret your problem, maybe you don't want to share the boards between the list of visitedBoards and WM (whatever it means...). Then simply implement get_Board() to return a copy of the array instead of the Board object itself:
public int[][] get_Board(int[][] src) {
int[][] dst = new int[src.length][src[0].length];
for (int i = 0; i < src.length; i++) {
System.arraycopy(src[i], 0, dst[i], 0, src[i].length);
}
return dst;return dst;
}
Beside this, as others already told you, you'd really better to adopt the standard Java naming conventions, use meaningful names, and encapsulate your x, y and int[][] in real application classes.
Presumably, the new State object contains a pointer to the same arrayList as before. You'll want to manually copy the array out to a new one (a "deep clone" or "deep copy" as it is called). You might find this useful: Deep cloning multidimensional arrays in Java...?
Every time you create a new instance of State, you pass it the same array (whatever is returned by WM.get_Board()).
You then add that same array to VisitedBoards when you call VisitedBoards.add().
The fact that you're creating new State objects is irrelevant, because only the return value of NextState.get_Board() gets added to the list.
As a result, the list VisitedBoards always contains several references to the exact same array.
As Raffaele has suggested, you'll be fine if you make sure get_Board() returns a copy of the array in stead of a reference to the original (assuming that doesn't mess up logic that exists elsewhere).
The main thing I learned from this question is how important it is to follow naming conventions.
Your unconventional capitalization has made me dizzy!
Following these rules will make it much easier for others to understand your Java code:
class names should be capitalized (ie PascalCase)
variable names should be lowercase (ie camelCase)
do not use underscores in method names, class names, or variable names (they should only be used for constants)
always use meaningful names when possible
My advice is to create your own container object for their 2D array and implement deep copying.
For example:
package netbeans;
import java.util.Arrays;
public class Container
implements Cloneable
{
private int [] _data;
private int _sx;
private int _sy;
public int get(int x, int y)
{
try { return this._data[y*this._sx+x]; }
catch (Exception e) { throw new ArrayIndexOutOfBoundsException(); }
}
public void set(int x, int y, int value)
{
try { this._data[y*this._sx+x] = value; }
catch (Exception e) { throw new ArrayIndexOutOfBoundsException(); }
}
public Object Clone() { return new Container(this); }
public Container(int sizeX, int sizeY, int [] data)
{
this._sx = sizeX;
this._sy = sizeY;
this._data = data;
}
public Container(Container cont)
{
this._data = Arrays.copyOf(cont._data, cont._data.length);
}
}
this may seem daft i have a class called ship locations which i wish to store all my ships locations, ive extended it from my client class and simply called the set method as follows
sub.local being a multidimensional array from the ship class
sub.local = new int[2][2];
sub.local[0][0] =row;
sub.local[0][1]=col;
sub.local[1][0]=row;
sub.local[1][1] =col+1;
toServer.writeInt(row);
toServer.writeInt(col);
toServer.writeChar('s');
sub.placed=true;
setp1sub(sub.local);
When i print it back through another class it comes back with the location in the memory rather than the numbers i need. What is the reason for this
public class ShipLocations {
static int [][] p1sub;
public ShipLocations()
{
p1sub = new int[2][2];
}
public int[][] getp1sub()
{
return p1sub;
}
public void setp1sub(int[][] local) {
for (int i = 0;i <local.length;i++)
{
for(int j = 0;j<local.length;j++)
{
p1sub [i][j]= local[i][j];
}
}
}
}
would it be that im passing it as sub.local ?
output is [[I#a401c2
Instead of writing
System.out.println(yourArray);
use
// for multidemensional arrays:
System.out.println(Arrays.deepToString(yourArray));
// or for one dimemsional arrays:
System.out.println(Arrays.toString(yourArray));
Here is a link to the relevant JavaDoc.
For an explanation of your output, you can look at this answer.
Ok, here is the code and then the discussion follows:
public class FlatArrayList {
private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] currentRow = new int[10];
int counter = 0;
while (true) {
for (int i = 0; i < 10; i++) {
currentRow[i] = probModel.size();
}
TestWrapperObject currentWO = new TestWrapperObject(currentRow);
probModel.add(counter, currentWO);
TestWrapperObject testWO = probModel.get(counter);
// System.out.println(testWO);
counter++;
if (probModel.size() == 10) break;
}
// Output the whole ArrayList
for (TestWrapperObject wo:probModel) {
int [] currentTestRow = wo.getCurrentRow();
}
}
}
public class TestWrapperObject {
private int [] currentRow;
public void setCurrentRow(int [] currentRow) {
this.currentRow = currentRow;
}
public int [] getCurrentRow() {
return this.currentRow;
}
public TestWrapperObject(int [] currentRow) {
this.currentRow = currentRow;
}
}
What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop,
the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.
You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.
Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.
i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book
select isn't broken
it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)