Hi I'm new to Java and I just encountered the following problem in a homework. I'm required to write a class that adds a new object to list when a void method is called. As a hint, the structure of an iterator method is given, so the core structure of my code now looks like this:
public class objectList implements Iterable<Obj> {
private ArrayList<Obj> objectList;
attribute_a A;
attribute_b B;
attribute_c C;
public objectList(attribute_a A, attribute_b B, attribute_c C){
objectList = new ArrayList<Obj>;
this.A = A;
this.B = B;
this.C = C;
}
public void extendList(attribute_a A, attribute_b B, attribute_c C){
objectList.add(new Obj(A,B,C));
}
public Iterator<Obj> iterator(){
return objectList.iterator();
}
#Override
public String toString(){
newstr = "";
for(i = 0;i<objectList.size();i++)
{
//Assuming Obj has the method toString()
//It prints out all details of each object, then join into one string
newstr += objectList.get(i).toString();
}
return newstr;
}
}
I'm told to just use java.util.iterator, not a custom iterator - so it saved me from defining HasNext(), next(), remove(), etc.
Edit: my goal is to be able to print objects stored in objectList, after extendList() is called several times i.e. there are many items stored in the list. Now I can only print the latest item in it (only 1 item is in the list).
What do I have to do to make the "cursor" automatically point to next item -> get attribute -> perform tasks on the attribute -> next item, etc. until the list is finished?
Let's see what's going on here...
So, you have a class, and it has a field called objectList. When you create a new objectList instance, the constructor gets called and the field is initialised to an empty list. So far so good. (However, why do you have the fields called A, B and C? They don't seem to be used at all, so it seems confusing to require someone to pass three parameters to your constructor that are effectively ignored.)
Then, whenever extendList is called, a new Obj is added to the instance's list. That looks about right. This means that at any given point, we can say that the size of the objectList is equal to the number of times that extendList has been called on that object.
Equally, calling iterator will just return the standard Java iterator for this list. So that iterator should visit every Obj in that list, which will be a number of items equal to the number of times that extendList was called on the same objectList object.
So - why doesn't it work?
It's not clear from the code you've posted. Your class itself looks OK, so the conclusion is that you must be calling it wrong. My guess is that you're actually constructing multiple instances of the class - every time you call the constructor, you create a new instance with different fields. For example, this won't do what you expect:
new objectList().extendList("A1", "B1", "C1");
new objectList().extendList("A2", "B2", "C2");
new objectList().extendList("A3", "B3", "C3");
return new objectList().iterator();
because a new instance is created each time, effectively throwing the state away from before. You'd want to rewrite that as:
objectList ol = new objectList();
ol.extendList("A1", "B1", "C1");
ol.extendList("A2", "B2", "C2");
ol.extendList("A3", "B3", "C3");
return ol.iterator();
If that doesn't solve it, look at how you're using the class, count how many times you call extendList on the same instance that you get the iterator from. If in doubt - get Java to count for you - add System.out.println("in extendList") calls (and perhaps some in the constructor) to see what gets called when. In fact, if there's a concern that different instances of the class are being used, you can get a unique identifier for the specific instance with System.identityHashcode(), e.g.:
public void extendList(attribute_a A, attribute_b B, attribute_c C){
System.out.println("Extending list for " + System.identityHashcode() + " with " + A + ", " + B + ", " + C);
objectList.add(new Obj(A,B,C));
}
Failing that, it may be worth getting familiar with how to use a debugger, and stepping through your program line by line. This will let you see the state of your program at every step, and hopefully it'll make it clear to you where things start diverging from your expectations.
(I'll also encourage you to use standard Java naming conventions, as your code is surprisingly challenging to read at the moment without them. Class names should start with capitals (and be in UpperCamelCase). Variables and field names should start with lower case letters (and be in lowerCamelCase). At the moment your class name looks like a variable, and your fields look like generic parameters. new objectList() just looks wrong!)
Try initializing this objectList = new ArrayList<Obj>; out side the constructor,
private ArrayList<Obj> objectList=new ArrayList<Obj>();
Related
I still can't understand when and why should I use the "Obj obj = new Obj" and I don't get why it's so difficult for me.
In this assignment I need to create a method as it follows:
"insertSorted: This method assumes the input LinkedList is already sorted in non-descending order (i.e.,such that each element is greater than or equal to the one that is before it, and inserts the input int value into the correct location of the list. Note that the method does not return anything, but rather modifies the input LinkedList as a side effect. If the input LinkedList is null, this method should simply terminate. This is the code you're starting with:
public static void insertSorted(LinkedList<Integer> list, int value) {
/* IMPLEMENT THIS METHOD! */
}
Let alone all the complications about iterating the LinkedList list, I don't even know how to start.
Should I create a new LinkedList<Integer> newList = new LinkedList<Integer>(); so I can iterate through it right? Why though? If the list is given in the method signature should I assume that the Object is already created when the input is given in the method signature?
I am really confused. It seems that I can't quite catch the whole Object programming thing.
Obj obj = new Obj
well if want to understand the new keyword in one line its like a contract in memory area where you can store the data (thats not all but enough to start).
public static void insertSorted(LinkedList<Integer> list, int value) {
/* IMPLEMENT THIS METHOD! */
}
Now for this method you donot want to create any new object.
Q.Why?
Ans- when this method will called their is mandatory to pass some parameter to the method if not it will be a compile time error.
Passing values could be null.
Since the method returns void you should modify the list that is given as input.
I'll show you why with an example
public static void insertSorted(LinkedList<Integer> list, int value) {
LinkedList<Integer> list2 = new LinkedList<Integer>(list); //this means you are creating a new list of integers called list 2 with the same elements of the list "list" in the same order
//some code to add value to list2 maintaing the sorting
//no return needed
}
somewhere else you want to call this method
LinkedList<Integer> list = new LinkedList<Integer>();
list.Add(1);
list.Add(2);
list.Add(5);
for (Integer i : list) System.out.println(i);
//prints 1, 2 , 5
insertSorted(list,4);
for (Integer i : list) System.out.println(i);
//still prints 1, 2 , 5!
if now you run this code with a debugger and you break in the method insertSorted right after you inserted the value in list2 you will see that list "list" remains as it was at the start of the method (which is (1,2,5)) and the list "list2" will be (1,2,4,5).
But the caller method knows nothing about list2!!!
When you declare a variable within a method it dies when the method ends (unless you return it). Of course you should pay attention to the "aliasing", but this is not the case.
Your requirements are very clear: your method must modify the input rather than creating a new list.
You can't understand why you should create a new object just because you don't have to. Someone just gave you a wrong suggestion :)
Now it's up to you to iterate the list and insert the integer in the right place :)
I need to know why the following happens, in this code (the last two block) I expect the exact same output yet the local objects (who are mere references to the ones in the list, right?) are in their old state while the list is updated. I have a bug because of a similar copying procedure in my gamecode (tilebased, objects swap positions, so I thought why not just swap their references...)
Example:
package game;
import java.util.ArrayList;
public class Tester {
private String s;
private Foo foo;
public Tester(String s, String f) {
this.s = s;
this.foo = new Foo(f);
}
class Foo {
private String f;
public Foo(String f) {
this.f = f;
}
}
#Override
public String toString() {
return foo.f + ":" + s;
}
public void swap(Tester other) {
String tempS = this.s;
Foo tempFoo = this.foo;
this.s = other.s;
this.foo = other.foo;
other.s = tempS;
other.foo = tempFoo;
}
public static void main(String[] args) {
ArrayList<Tester> test = new ArrayList<Tester>();
test.add(new Tester("First", "1"));
test.add(new Tester("Second", "2"));
System.out.println("After initializing list");
for (Tester t : test) {
System.out.println(t);
}
Tester first = test.get(0);
Tester second = test.get(1);
Tester tmp = first;
first = second;
second = tmp;
System.out.println("\nAfter temps");
System.out.println(first);
System.out.println(second);
System.out.println("\nList changed after temps?");
for (Tester t : test) {
System.out.println(t);
}
System.out.println("\nAfter swap");
first.swap(second);
System.out.println(first);
System.out.println(second);
System.out.println("\nList after swap");
for (Tester t : test) {
System.out.println(t);
}
}
}
And the output:
After initializing list
1:First
2:Second
After temps
2:Second
1:First
List changed after temps?
1:First
2:Second
After swap
1:First
2:Second
List after swap
2:Second
1:First
I think I was a bit unclear, I always print out first then second (the objects) so "After swap" should look exactly like "List after swap", the list has changed after the swapping of the local objects, the local objects (again, mere references to the ones in the list?) have not.
To the comment in the answer: While my confusion is cleared and my problem solved I was asking whether it is possible to get the actual reference of the list to the object so that when I point it to something else the list will also automagically point to that something else. In the example below Foo a points first to object Foo with attribute A, but this reference it got from list.get(). Now if I point it to new Turtles() the list will still point to Foo with A.
I was hoping for a "hard" reference, so that when I point to turtles, the arraylist points to turtles.
This would make swapping easier but I am yet unsure of how to implement a list that can do this (if at all possible), this would suit the specific needs of my game very well.
What you need to bear in mind when working with objects is that the variable which holds the object doesn't actually represent the object. The value of the variable is a pointer in memory to the place where the object exists.
An ArrayList of a certain type of object, by extension, doesn't actually hold objects. It holds object references, or pointers to object locations in memory.
When you say:
Object a = new Object();
Object b = new Object();
a = b;
you're setting a to the value of the pointer to b; in other words, since both a and b point to the same object in memory, changing one changes the other.
Now to answer your question, with this in mind. If you pull two object references out of an ArrayList, and then swap them, you've swapped the references to the objects; however, the references haven't changed location in the ArrayList. This explains the first three outputs.
Once you do an internal swap, however, you've changed the values stored in each object. This means that, though the pointers to the first and second objects are still the same in memory, their internal information has been swapped.
This explains the last two outputs.
(Note, this is also why you have to use System.arraycopy instead of setting int[] a equal to int[] b; if you were to do the latter, then changing a would change b.)
Actually your swap method does not swap the objects themselves but only the values they are containing, the String s is swaped by value, the object foo is swaped by reference.
when you get an element from the list using get(index) you actually get a reference to that object in addition to that internal reference witch the list is holding, so you have there two references pointing to the same object.
to really swap element of a list you should be using the set method of the List with something like that:
Tester tmp = test.get(index);
test.set(index, test.get(index+1));
test.set(index+1, tmp);
this way the elements are swaped in the list so iterating over it will print the result you expect. the swap method you have will be obsolete.
If I have code that looks like this:
Collection<Object> c = new HashSet<Object>();
will it still retain the properties that the collection will not be able to contain duplicate values. In other words, what would happen in the following situation?
String h = "Hello World!";
c.add(h);
c.add(h);
Yes, the behavior and properties of Set will still hold. c will only contain one instance of "Hello World!"
public static void main(String[] args)
{
Collection<Object> c = new HashSet<Object>();
String h = "Hello World!";
c.add(h);
c.add(h);
System.out.println("c contains " + c.size() + " item(s): " + c);
System.out.println("c is an instance of " + c.getClass());
}
The above main method outputs:
c contains 1 item(s): [Hello World!]
c is an instance of class java.util.HashSet
You're not "constructing a Collection"; you're merely create a new reference. So yes, all the underlying properties still hold, because it's still the original object's methods that you're calling.
Short: yes - it is still an object of HashSet even if the referencing variable type is a super type of HashSet.
HashSet<T> theSet = new HashSet<T>();
Collection<T> collection = theSet;
Iterable<T> iterable = theSet;
Object object = theSet;
All of these four variables are of different types (all of them have to be super types of HashSet by the way), but all of them refer to the same object whose type is HashSet. No matter what variable you use to access the object, it will always behave in the same way. This is one of the key features of polymorphism.
The only difference is that the higher you move the inheritance tree (up means towards more general types), the less methods and fields are accessible for you. So you cannot call methods such as object.iterator(), iterable.size() etc., but when you call a method common for all the variables, it always behaves the same way:
theSet.toString(); // produces []
collection.toString(); // produces []
iterable.toString() // produces []
object.toString(); // produces []
String h = "Hello World!";
c.add(h);//Returns true
c.add(h);//Returns false since duplicate elements are not allowed in HashSet
So only one instance of h will be added to HashSet
Is there a way to move the entire contents of an ArrayList to another instance of ArrayList in O(1)?
I.e.: only the reference to the backing array is passed from one instance to the other (elements are not copied one by one).
For example:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = new ArrayList<>();
a.moveContentsTo(b);
// 'a' is now empty, while 'b' contains everything that 'a' did before and 'a != b'
// It is desired that the 'moveContentsTo' method is O(1)
Even better, is there an ArrayList#swapContents(ArrayList) method?
Further explanation and use-case:
Further explanation 1: the references of 'a' and 'b' must not be exchanged. I am not looking for tmp = a; a = b; b = tmp; type of solutions.
Further explanation 2: The operation must be ~O(1) in time.
The use-case: This is useful when an object wants to encapsulate a list constructed outside:
public class A {
private ArrayList<String> items = new ArrayList<>();
/**
* This method takes the sole ownership of the contents. Whoever
* passed the list from the outside will not be able to modify
* contents of 'this.items' from outside the class.
*/
public AnImmutableObject(ArrayList<String> items) {
if (items != null) {
items.moveContentsTo(this.items);
}
}
/**
* Other collections that do not provide the 'move' functionality
* must be copied. If we just stored the reference to 'items' we
* would break encapsulation as whoever called the constructor
* still have write capabilities to the collection.
*/
public A(Collection<String> items) {
if (items != null) {
this.items.addAll(items);
}
}
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
}
Notice that we want to avoid making a copy (to increase speed and decrease memory usage). The crucial bit is that the callee must lose the ability to modify the (now encapsulated) ArrayList.
#Lirik answer is greate +1. However, if you are looking for a real ArrayList#swapContents(ArrayList), here is how you can do it:
public static void swapContents(ArrayList<String> listA, ArrayList<String> listB)
{
List<String> temp = new ArrayList<String>(listA);
listA.clear();
listA.addAll(listB);
listB.clear();
listB.addAll(temp);
}
AFAIK, it's very not Java-like to keep track of "ownership" of references (at least on the programmer's side) which is why I doubt that you'll find the std::move()-like functionality that you want. It just isn't very commonly needed in Java.
I guess C++ needs to keep track of object ownership explicitly because there is no garbage collection.
I think that your best bet is to create a defensive copy in your constructor and save space by relying on copy constructors of immutable objects:
public class AnImmutableObject {
private final List<String> items;
/**
* Creates a new immutable object with the given list of items.
* Always deep copy from an outside source, because we can't know if the
* calling code will modify that collection later.
*/
public AnImmutableObject(Collection<String> items) {
// It's a constructor. We know items needs to be set.
// We are creating a new array list, using its constructor which deep
// copies the collection, and immediately wrapping it to make it truly
// immutable. We are guaranteed that no one will hold a reference to the
// mutable view of the new ArrayList.
this.items = Collections.unmodifiableList(new ArrayList<String>(items));
}
/**
* Creates a new immutable object with the same items as another.
* Copying the reference here is completely safe because we
* enforce the immutability of the items array.
*/
public AnImmutableObject(AnImmutableObject source) {
items = source.items;
}
public List<String> getItems() {
return items;
}
}
At this point, you can "pass the arrays around" (really share them) in O(1) between your own immutable objects:
ImmutableObject a = new ImmutableObject(Arrays.asList("A", "B", "C")); // O(n)
ImmutableObject b = new ImmutableObject(a); // O(1)
Hopefully, something like this can suit your purposes.
Another route you could go is use Guava's ImmutableList. Since these are immutable, you can safely copy the reference to the ImmutableList in a constructor.
The main approach is about making it safe for you to copy references to the lists rather than taking ownership over them.
This should do it:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = a;
a = new ArrayList<>();
Conceptually speaking, a is now empty and b contains what a contained before. There was a single assignment and no copying of data, which is about the fastest you can do it. Does that satisfy your requirement, or do you actually want a to still reference the same array except that the given array should now be empty?
Update
I don't believe that in C++ the time complexity for the move operation is O(1) either. It's also prudent to point out that "because classes in Java use reference semantics, there are never any implicit copies of objects in those languages. The problem move semantics solve does not and has never existed in Java." (see the answer by FredOverflow: C++ Rvalue references and move semantics)
Is there a way to move the entire contents of an ArrayList to another ArrayList so that only the reference to the backing array is passed from one to the other (i.e., so that elements are not copied one by one).
Given the above statement, then if you copy something from array a to array b in Java, both arrays will reference the same data. All that you do with move semantics in C++ is that you save the temporary object which needs to be created in order to make such a copy:
X foo();
X x;
// perhaps use x in various ways
x = foo();
The last one does:
destructs the resource held by x,
clones the resource from the temporary returned by foo,
destructs the temporary and thereby releases its resource.
Move semantics does:
swap resource pointers (handles) between x and the temporary,
temporary's destructor destruct x's original resource.
You save one destruct, but only in C++... the above problem does not exist in Java! See this article for more details on move semantics: http://thbecker.net/articles/rvalue_references/section_02.html
I am unable to understand how this works
public void addToRule(Rule r) {
if (!getRuleList().contains(r)) {
getRuleList().addElement(r);
}
}
If I run this code:
obj.addToRule(r);
System.out.println(getRuleList().contains(r));
it prints out true how can this happen?
btw ruleList is a vector member of the main class and is not a static variable(don't think this matters but sharing anyway).
import java.util.Vector;
public class RuleEngine{
private Vector ruleList = new Vector();
public Vector getRuleList(){
return ruleList;
}
public void addToRule(Rule r){
if(!getRuleList().contains(r))
getRuleList().addElement(r);
}
public static void main(String args[]){
RuleEngine re = new RuleEngine();
Rule r = new Rule("Rule1");
re.addToRule(r);
System.out.println(re.getRuleList().contains(r));
}
}
class Rule{
public String name = "";
public Rule(String nam){
this.name=nam;
}
}
OK people have told me that this works because of the pass by reference in java. I get it. but what can i do to get a copy of that object instead of its reference?
I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().
For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.
These assumptions are of course without seeing your full code.
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Hope I could help,
Ferdi265
From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.
Consider
class Test {
private List list = new ArrayList();
public List getList() {
return list;
}
}
The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like
Test test = new Test();
String s = "ABC";
test.getList().add(s);
System.out.println(test.getList().contains(s));
Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.
Consider this, however.
Test test1 = new Test();
Test test2 = new Test();
String s = "ABC";
test1.add(s);
System.out.println(test2.getList().contains(s));
This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.
It should always print true, because you add the rule to the rule list in case it is not there. What happens is:
you tell the object to add add a rule to its rule list
the objects checks if the rule exists, and if it doesn't, adds it
So it is guaranteed to contain the rule after the code is executed.