I'm trying to make an ArrayList of my own type to store some values. However, I'm getting an error "x cannot be resolved or is not a field", where is source for example.
Here is a snippet of my code:
public class myClass {
public static void main(String args[]){
addEdge("a","b", 10);
}
private static void addEdge(String source, String destination, int cost) {
List<Edge> add = new ArrayList<Edge>();
add.source = source; //error: source cannot be resolved or is not a field
add.destination = destination; //error: destination cannot be resolved or is not a field
add.cost = cost; //error: cost cannot be resolved or is not a field
}
}
class Edge{
String source;
String destination;
int cost;
}
As you can see I get errors in my addEdge method. I'm
In your code
List<Edge> add = ...
add.source = ...
you are trying to access source field via add reference which is of type List but List doesn't have source field (which is what error message is trying to say). You need to access this fields from Edge, not from List.
So try something more like
Edge edgeInstance = new Edge();
edgeInstance.source = source;
edgeInstance.destination = destination;
edgeInstance.cost = cost;
...
listOfEdges.add(edgeInstance);
Anyway you should avoid making your fields accessible from outside of your class. They should be private and you should initialize them via constructor or via setters.
Also it seems that each time you are calling your method you are creating new List
List<Edge> add = new ArrayList<Edge>();
and you are not reusing it anywhere outside of this method which seems kind of pointless.
Assuming the List and ArrayList types you are referencing in your addEdge method are Java's own java.util.List etc., they don't have accessible properties named source, destination or cost.
If the ArrayList is your own implementation, it does not feature source, destination or cost fields.
The idiom you want to use here is reference an Edge instance and mutate its fields.
To do so, you would do:
add.get(x).setSource("some source");
That implies:
Your List is not null nor empty
x is a valid index
The Edge element at index x is not null
You implemented setters/getters for your Edge fields
By defining list of type Edge, you dont get field's defined within edge. It's a list where you could add/remove/iterate elements within it.
In your case, List can only add object of type Edge. So you need to create Edgle like:
List<Edge> add = new ArrayList<Edge>();
Edge edge = new Edge(source, destination, cost);//add constructor to your edge class like public Edge(Source source... ){ this.source = source;.. }
add.add(edge);//rename list to meaningful name like edgeList
Related
I'm implementing a Graph in Java.
The Graph class uses a LinkedList for the vertices. And each vertex also contains a LinkedList of adjacent vertices.
I'm still working on my methods. I just need a quick clarification with a getVertex() method which accepts a String label and returns a Vertex that matches that label.
public class Graph
{
private class Vertex
{
private String label;
private LinkedList links;
private boolean visited;
Vertex(String label)
{
this.label = label;
LinkedList links = new LinkedList();
visited = false;
}
private void addEdge(Vertex vertex)
{
links.insertLast(vertex);
}
private String getLabel()
{
return label;
}
private LinkedList getAdjacent()
{
return links;
}
private boolean isVisited()
{
return visited;
}
private void visit()
{
visited = true;
}
private void unvisit()
{
visited = false;
}
}
/* Classfields for Graph Class */
private LinkedList vertices; //Linked List for the vertices in the graph
private int vCount;
private int eCount;
public Graph()
{
LinkedList vertices = new LinkedList();
vCount = 0;
eCount = 0;
}
public void addVertex(String label)
{
Vertex newVertex = new Vertex(label);
vertices.insertLast(newVertex);
vCount++;
}
public int getVertexCount()
{
return vCount;
}
public Vertex getVertex(String label)
{
// what to return?
}
It should be very simple, but I can't understand how I'm going to import this label but return a Vertex, working with a LinkedList. Would appreciate any tips!
If you are working on assignment on an assignment, and you are expected to use LinkedList that's fine, but it's the best choice of collection that serves as a storage of all vertices in the graph and also as the adjacency list of vertex
I suggest you addressing these issues:
Firstly, don't use row types LinkedList links, you should always specify a generic type parameter List<Vertex>.
Write your code against interfaces, not against implementations. I.e. use List<Vertex> instead of LinkedList<Vertex>. It makes your code more flexible.
In order to be able to retrieve a particular vertex by label, you can use a Map<String, Vertex> to store all vertices of the graph. With that time complexity of the getVertex() will be reduced to constant time, it's way faster than iterate over the list. And the code is a single line vertexByLabel.get(label).
Maintaining a variable that hold a count of vertices is redundant because you can check the size of collection of vertices to get this value.
ArrayList performs than LinkedList and has a better memory consumption. For that reason, it considered to be a general purpose implementation of the List interface and it's a preferred choice if you don't expect use cases like removal of elements by the means of Iterator while iterating over the list (which will be done in constant time, here LinkedList really shines). Also, HashSet might be useful in a role of the collection of adjacencent vertices because it will all you to ensure that there will be no duplicates.
So in regard to getVertex() method, if you'll agree with the suggestion to use map, the code will look like this:
private Map<String, Vertex> vertexByLabel = new HashMap<>(); // it is advisable to initialise collections, if you are not passing argument with collection that holds values to the constructor, but just assigning a new collection
public Vertex getVertex(String label) {
return vertexByLabel.get(label);
}
I also advise you to make changes to the methods addVertex() and addEdge(). Firstly, I would rather expect to a method called addVertex() inside the Vertex class (we are adding a new vertex to the adjacency list of this vertex) and a method addEdge() inside the Graph (we are connecting vertices inside the graph).
And if order to connect the vertices method addEdge() of the graph will expect a vertex label as its first argument, and labes of the adjacent vertices as a variable arity argument (varargs).
In case if you have a strong requirement to utilize LinkedLinked exclusively and not allowed to use generic types. But frankly spiking, it doesn't seem a bright idea to disallow student to use generics. It doesn't reduce complexity a lot because instead you have to deal with manual down-casts, and it's a very bad practice.
Your method might look like this:
public Vertex getVertex(String label) {
Vertex result = null;
for (Object next: vertices) { // all elements in the collection of row type a treated by the compiler as being of type Object
Vertex vertex = (Vertex) next; // you need to cast the element into the Vertex type in order to be able to access its field `label`
if (vertex.label.equals(label)) {
result = vertex;
break;
}
}
return result;
}
This is my sample class
public class Value<E> {
public final E value;
public Value(E value) {
this.value = value;
}
}
And this returns a String and no Object, so I don't need to cast it.
String a = new Value<String>("test").value;
However, if I want to do this, then I need to cast it.
ArrayList<Value<?>> a = new ArrayList<>();
a.add(new Value<String>("test"));
String b = a.get(0).value; // Runtime error
If I add the value to the ArrayList it returns an Object, but I want it to return what I defined the Element to be.
How can I solve this?
Replace
ArrayList<Value<?>> a = new ArrayList<>();
with
ArrayList<Value<String>> a = new ArrayList<>();
You can't. You defined that you don't know (or care) what types are contained inside with Value<?>, so you can only treat them as Object as that's the one thing they're guaranteed to be (they can also be subclasses, but they'll still always be Objects too).
If you think and hope you can store Strings and Integers in the same List, that's not possible except by treating them as Objects. Besides, you shouldn't be storing different types (except through inheritance hierarchy) in the same collection anyway.
This is my first problem I can't solve by searching. It's a general OOP problem, but the code is in java. Perhaps I miss an essential point?
Assume there is a baseclass and a subclass. An object of the baseclass is in many lists. There is a transformer class with one duty to transform the object into a subclass object. The transformer should not know anything about the lists. But as a result of the transformation the new subclass object should be in all the lists. (replace the former base class object)
Can this be done somehow?
class BaseClass {
//
}
class SubClass extends BaseClass{
//
}
class Transformer{
BaseClass base;
public Transformer(BaseClass base){
this.base = base;
}
public void transform(){
//transforms the Object to a subtype-object
// ???
// (move the references of the old object to the new one)
this.base = new SubClass(); //something like this (but not so!!!)
}
}
class Programm{
private List<BaseClass> list1 = new ArrayList<>();
private List<BaseClass> list2 = new ArrayList<>();
private List<BaseClass> list3 = new ArrayList<>();
//many more Lists
private List<BaseClass> listn = new ArrayList<>();
public void main() {
BaseClass myObject = new BaseClass();
list1.add(myObject);
list2.add(myObject);
list3.add(myObject);
listn.add(myObject);
Transformer transformer = new Transformer(myObject);
transformer.transform();
//required result
// All Lists contain the transformed Object (from Type SubClass)
}
}
What you're trying to do is luckily impossible (imagine if your objects started changing classes in the middle of your code). You can create a subclass object based on a superclass object (if you can sensibly fill in any missing properties), but you can't turn an existing object into its subclass (such that the reference equality would work as you're hoping in your example code, i.e. converting myObject would affect all the lists).
I don't know how you came up with this idea, but somewhere along the way you've gone down the wrong path. If you tell us what you're trying to achieve, we can provide you with a better solution.
Edit:
Since you're doing checkers and you need to crown a piece, you have the simple choice of adding a boolean crowned property to pieces, and writing logic based on that.
In a more complex situation you could for example use the strategy pattern, where you would have a Piece class, and they would have a Type property that specifies the actual type of the piece. This way the object you put in lists (Piece) always stays the same, but if you replace its Type property, it would seem as if the piece magically changes it's type!
I know that in Java due to inheritance, a superclass type variable can hold a reference to a subclass object. Example, say ClassA is the superclass to ClassB. You could set an element of a ClassA[] to reference a ClassB object. I'm running into a problem doing this while using a copy constructor of the subclass.
public Items copyFromMasterInventory(String str){
Items itemToReturn = null;
int length = masterInventory.length;
int iterator = 0;
while (iterator < length){
String name = masterInventory[iterator].getName();
if (name.equals(str)){
if (name.getClass().equals(Collectible.class)){
itemToReturn = new Collectible(masterInventory[iterator]);
}
if (name.getClass().equals(Props.class)){
itemToReturn = new Props(masterInventory[iterator]);
}
}
}
return itemToReturn;
}
In this case, there are three class. Items, Props, and Collectible. Props and Collectible are subclasses of Items. masterInventory is an array of Items storing both Collectible and Props objects. The purpose of this method is to create and return a copy of an item in the masterInventory array. To avoid .clone(), I've created copy constructors for Collectible and Props. But the way I have it now shows an incompatible types error, that Items cannot be converted to Collectible or Props, even though the object stored in that element is a Collectible or Props object. If been reading and searching for hours but can't seem to come up with a solution. Does anyone know a way around this issue? All help is appreciated.
You could add an abstract method Item getCopy() to the Item class, implement it in both Props and Collectible, and call it in de while loop:
itemToReturn = masterInventory[iterator].getCopy();
the benefit here is that you do not need the condition on class.
The solution is simple - casting :
if (masterInventory[iterator] instanceof Collectible) {
itemToReturn = new Collectible((Collectible) masterInventory[iterator]);
}
if (masterInventory[iterator] instanceof Props) {
itemToReturn = new Props((Props) masterInventory[iterator]);
}
The more I google this the more confused I'm getting.
I'm bringing in a list of names of unknown length with some other details in from a CSV which I then need to turn into Person objects and store in a list called people which is the instance variable for the class Club, a list of its members basically.
This is a very simplified version of something more complex I need to do in which I need to while loop through a file creating objects for each line which I then need to add to a list collection.
I keep getting a nullPointerException error when I run my code though and I'm stumped how to avoid it. I'm guessing that my variable p when I create the new object would need to change on each loop but I don't think it's possible to change variables dynamically is it?
Can't think how I can commit the object to the collection with a valid non null reference each time. Would be very grateful for any help. I've tried to cut out all the unnecessary stuff in the code below.
Thank you
//class arraylist instance variable of class "Club"
private ArrayList<Person> people;
//class constructor for Club
public Club()
{List<Person> people = new ArrayList<>();}
public void readInClubMembers()
{
//some variables concerning the file input
String currentLine;
String name;
String ageGroup;
while (bufferedScanner.hasNextLine())
{
//some lines bringing in the scanner input from the file
name = lineScanner.next();
ageGroup = "young";
Person p = new Person(); // i guess things are going wrong around here
people.add(p);
p.setName(name);
p.setAgeGroup(ageGroup);
}
}
Remove the List<Person> before people = … inside the constructor, otherwise you are declaring a new local variable people inside the constructor shadowing the field people (which is then never used). This leaves the class field uninitialized (null) and then causes the NPE.
What you want instead is initializing the field people:
public Club() {
// you can also use "this.people = …" to be explicit
people = new ArrayList<>();
}
To show the difference:
class Example {
private int myNumber;
public Example() {
myNumber = 42; // sets the field of the class
int myNumber = 1337; // declares a new local variable shadowing the class field
myNumber = -13; // accesses the object in the closest scope which is the local variable
this.myNumber = 0; // explicitly accesses the class field
}
}