Will constructing a Collection using a Set retain the Set properties? (Java) - java

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

Related

Making an Integer array inside Object class reference variable

If i try to make array of Object class in java, it works fine
Object[] o = new Integer[]{1,2,3};
for(Object x : o)
System.out.print(x);
Output is: 123
I found out that you can also do
Object o = new Integer[]{1,2,3};
It doesn't give compile fail. I want to know that can we iterate through the Integers in reference 'o' ?
Then i tried this
class A{ }
class B extends A{ }
class App{
public static void main(String[] args) throws InterruptedException {
A a = new B[4];
}
}
But her A a = new B[4]; gives CF
Every single Object-type in Java inherits from the Object class.
So, basically: an Integer is an Object, which is why you can do this:
Object[] o = new Integer[]{1,2,3};
On the other hand, Arrays are Objects, too, meaning you can do this:
Object o = new Integer[]{1,2,3};
In the first example, the Integers are the Objects, in your second, the Object o is a reference to the Array of Integers
UPDATE: The reason between your A and B classes, you do have an Exception, is because even though each B is an A, the Array in which you store your B's is not an A.
Java arrays are covariant. Meaning that, You can use a Sub type in place of Type.
So if you have an array of "Type", you can actually fill that array with "SubType"'s. Well, any class in Java is a Subtype of Object. Hence no error in that case.
Object o = new Integer[]{1,2,3};
It doesn't give compile fail.
Again the same things, as Array is also an Object in the end, hence you are free to assign that to an Object.
I want to know that can we iterate through the Integers in reference 'o' ?
By default, Object is not iterable. Where as Array object is.
So before you going to iterate, you have to cast it to type Array.
Update :
But her A a = new B[4]; gives CF
Ofcourse that is not a valid declaration You should write
A[] a = new B[4]; // just to satisfy the compiler. At run time you are not allowed to store A's in it.
But if you are trying to achive the style
Object o = new Integer[]{1,2,3};
No that won't work here and you can only write
Object o = new B[4];
That is because array is a sub type of Object class and not A class.
The reason this is possible is that an array is a subclass of Object. However, by storing the array in o, the program "forgets" the fact that o is holding an array. For that reason, you cannot iterate over o.
The compiler will only allow you to do things that it "knows" you can do to that particular class. Here's an analogy: you want to haul 1 metric ton of sand for a few miles. Would you request a "vehicle," or would you specifically request some kind of truck that you knew would be large enough to haul the sand? If you request a "vehicle of some kind," for all you know they might send you a Prius, which obviously wouldn't do you any good - a Prius can't haul 1 ton of sand. In this case, the compiler would "complain" that there's absolutely no guarantee that you'll be sent a vehicle that has the capacity to do what you want.
Types work that way, too - by default, it's perfectly valid to upcast the array to type Object, since everything in Java is a subtype of Object. But, from the compiler's perspective, there's absolutely guarantee that you can iterate over something of that type, so it won't let you do that.

How does iterator work with constructor

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>();

How can I cast Objects, considering that I already know the expected Java type?

Considering this part of a Java class,
private List<Object> components = new ArrayList<Object>();
private A a;
private B b;
private C c;
add(a, b, c);
public void add(Object... component){
for(Object o : component) {
components.add((CAST)o);
}
}
I would like to cast my Object o in the list, by the good type.
The expected result here would be to have A a, B b, C c in my list.
I try with getClass(), but I didn't compile. How can I upcast Objects, considering that I already know the expected Java type?
edit:
I need to add a first object of type A, a second object of type B, a second object of type C, ... (I don't know the number of items to add) if a list so that I will be able to get the list containing N objects correctly typed. (gtt(0) would be typed as A, get(1) as B, and get(2) as C )
Because I don't know the number of objects and that I initially don't know the object's type, I delclared my list as Object.
I created a method (add in that case). It varargs will help me for looping in the collection because I don't know the number of args.
I would simply like to get the first object, the second object and the third object (and so on) in my varargs, and to simply push it in my list, but not as Object type, as A, B or C, depend of what I received!
I don't know if it's more clear.
Your list already accepts Objects
private List<Object> components = new ArrayList<Object>();
why do you need to upcast?
First, you can never upcast in this case. The only place you REALLY need an upcast is when you're accessing a method specific to C, not in B or A; or specific to B not in A. (or neither in Object)
You seem to be misunderstanding how the runtime type of an object works. When you put an 'A' into a List it does not stop being an 'A' and become an Object. If you take it out later and cast it back to an 'A' it is still the original runtime type. There is nothing gained by casting it before putting it in the list.
Consider this
Object str = "FOO";
List<Object> list = new LinkedList<Object>();
list.add(str);
String str1 = (String) list.get(0);
System.out.println(str1.length());
Prints '3'. "FOO" never stopped being a String just because the reference type of the pointer to it was Object.
To be honest, I agree with everyone above, that it doesn't make much sense upcasting in the example you gave. Since you declared that the list will contain Objects, you will have to do the cast again when retrieving the object from the list.
However, there is allways the type comparison operator instanceof which you could use.
public void add(Object... component){
for(Object o : component) {
if(o instanceof CAST)
components.add((CAST)o);
}
}

Why does it generate same hash code for both string objects?

I am new to Java programming, I want to create are multiple numbers of strings, for that I written the code below. Why does it generate same hash code for both string objects?
class SingletonClass {
public static String mystring="this";
}
public class SingletonObjectDemo {
public static void main(String args[]) {
String str = SingletonClass.mystring;
String str2 = SingletonClass.mystring;
System.out.println("String str "+str.hashCode());
System.out.println("String str1 "+str2.hashCode());
}
}
It's generating the same hash code for both string objects...because they're the same object.
They reference the same object in memory, there is in essence no difference..
You may be confusing objects with references to them. When you write String str = "a", str2 = "a"; you are not creating two strings, but declaring two variables which contain the exact same reference, to the string constant "a".
Even if they were two objects, as in String str = new String("a"), str2 = new String("a") the hashCodes would still be the same because for equal objects their hashcodes must match — that's the essential property of a hashcode.
But, if you wrote Object o = new Object(), o2 = new Object(), now the hashcodes would be different because no two instances of Object are equal (according to the definition of equality for the Object class).
You say you "want to create to multiple number of strings" but you are using something called SingletonObjectDemo. The point of a singleton is that there will only be one object, no matter how many times you "create it", so you can't create multiple objects. As Louis explains, that's why the hash code returns the same.
This is the property of a good hashcode.
If A and B are objects such that A.equals(B), then the following property should hold.
A.hashCode().equals(B.hashCode())
You can read about hashCode and equals() here

Why do you name the class twice during instantiation in Java?

When you instantiate an object, why do you specify the class twice?
OddEven number = new OddEven();
Why can't you just say number = new OddEven();? When I declare a string, I only say String once:
String str = "abc";
Actually, my question is not "why do you do it this way" -- obviously, you do it because you have to -- but rather, why did the creators choose to make Java syntax work like this?
My thoughts are:
There is something fundamental to the way Java operates at a low level that necessitates typing the name twice, or
The creators freely choose to do it this way to keep some aspect of the syntax uniform -- declare the type first? Or was it to be more like its predecessors?
Because you can do this:
Superclass x = new Subclass();
The type of the reference can be a superclass of the actual object being declared, so you need to specify both. For example, you can do:
List<String> stringList = new ArrayList<String>();
Your program interacts with objects that implement List, and you don't care about the implementation.,
The reason for the seemingly redundant type name is that you are performing two separate operations, each of which requires you to specify a type.
On the left side, you are declaring a variable (a storage location) with a particular type. On the right side, you are creating a new object with a particular type. The '=' in the middle causes a reference to the new object you created to be placed in the storage location you created.
The types on each side do not have to be the same. This, for example, is legal code:
Object number = new OddEven();
The reason that the keyword String only shows up once in your second example is that the type String is implied on the right hand side since "xxx" is a String constant. It is simply shorthand for:
String string = new String("xxx");
When you write:
OddEven number = new OddEven();
You actually do two things : 1) you declare a variable number of type OddEven and 2) you assign a reference to a new instance of class OddEven. But because a variable can hold any subtype of a type, writing number = new OddEven(); wouldn't be enough for the compiler to know the real type of the number variable. So, you have to declare it too. Java is a strongly typed language, which means that every variable and every expression has a type that is known at compile time. You may want to read the whole Chapter 4. Types, Values, and Variables of the Java Language Specification (JLS) to learn more on this.
Now, when your write:
String str = "abc";
Things are a bit different. Characters enclosed in double quotes, "abc" here, are called a string literal which is already a reference to an instance of String and always refers to the same instance of class String. Quoting the section 3.10.5 String Literals of the JLS:
Each string literal is a reference
(§4.3) to an instance
(§4.3.1, §12.5) of class
String (§4.3.3). String
objects have a constant value. String
literals-or, more generally, strings
that are the values of constant
expressions (§15.28)-are
"interned" so as to share unique
instances, using the method
String.intern.
So, String str = "abc"; is certainly not converted into String str = new String("abc"); which is absolutely not equivalent as I've read in some comments and answers. Running the following class:
public class Test {
public static void main(String[] args) {
String one = "abc";
String two = "abc";
String abc = new String("abc");
System.out.println(one == two);
System.out.println(one == abc);
}
}
Produces the output below:
true
false
And demonstrates that one and two are references to the same instance but that abc is a reference to another instance (i.e. an extra unnecessary object has been created).
Actually, using new String(String) is a inefficient way to construct new strings and should only be used to force a substring to copy to a new underlying character array, as in
String tiny = new String(monster.substring(10,20))
Think of 'OddEven number' as defining the Object and 'new OddEven();' as filling the object.
I'm not going to get into detail about superclasses and subclasses because other people have explained it already.
When you say String name = "foo", internally Java compiler creates a String object with the value "foo" and it assigns its reference to name variable. So, here instead of creating a new String object, we are assigning a reference to the other String object.
Btw, the compiler anyway creates "foo" for us. It first looks in String Pool, if it not exists, only then it creats "foo". Otherwise, Compiler returns a reference from String pool. This is some optimization that Java compiler performs internally.
String name = "foo" is simlar to OddEvenNumber oddEven = anotherOddEvenObject;
Array example:
declaration and initialization - when you know the length of the array:
int[] numberArray = new int[10];
declaration then initialization - when you don’t know the length of the array yet and might get it from a method or user input
int[] numberArray;
int length = 10; // let’s say we got this from the user
numberArray = new int[length];
Initialization only - when you don’t need to reuse:
return new int[10];
First OddEven is the type, second is the instance. It need not be even OddEven, it could be any subclass of OddEven. It does not mean you have type it twice. Any IDE have code templates where you have to type the name only once.
The first declaration is the type of variable you want to use in the scope you have, in this case it is OddEven, the second declaration is the constructor to use for instantiating (and in this case initializing) the reference.
You could have said INumberInstance = new OddEven(), where INumberInstance is some class which OddEven can be cast to (like a super of OddEven for instance).
The way to create a new object in java is:
Class_name reference_variable = new Class_name(param_if_any);
But the string class is an exception.
You can create a new string object as
String s = "abc";
or
String s = new String("abc");
Further to what Jim said, Java is a statically typed language. That means that every varable has a type that is know at compile time.
For instance:
public class A
{
public void foo() { }
}
public class B
{
public void foo() { }
}
public class Main
{
public static void main(final String[] argv)
{
A a = new A();
B b = new B();
a.foo();
b.foo();
}
}
the compiler looks at "a.foo()" and "b.foo()" and checks to see that a is of type A and A has a method called "foo" that takes no arguments. The compiler does the same for "b.foo()".
If you could write main like this:
public class Main
{
public static void main(final String[] argv)
{
a = new A(); // in Java you would really do Object a = new A();
b = new B(); // in Java you would really do Object b = new B();
a.foo();
b.foo();
}
}
then the compiler could not do that verification and it would have to happen at runtime.
The designers of Java did not have to make the syntax redundant. Scala is another language using the JVM, and it's also statically typed. Scala uses type inferencing to cut out verbosity. For instance here's a declaration of a variable of type MyPair called x. MyPair associates two variables with each other. It's a generic class, so you can specify that the first variable have type Int and the second the type String:
var x: MyPair[Int, String] = new MyPair[Int, String](1, "scala")
Scala type inferencing lets you remove the redundant type declaration:
var x = new MyPair[Int, String](1, "scala")
And Scala even infers types based on the constructor arguments, so you can write it this way:
var x = new MyPair(1, "scala")
Consider the following example,
We can specify the object type as follows,
List<String> abc;
In method1(), if you want to use array list which suits the best for it requirements then we can instantiate like as follows,
abc = new ArrayList<String>();
In method2(), if you want to use Linked array list which suits best for it requirement then we can instantiate like as follows,
abc = new LinkedList<String>();
So, the idea is that we can specify the type of "SuperClass" and instantiate with whatever subclass suitable for different requirements like "LinkedList" and "ArrayList" in the appropriate operation dynamically.

Categories