My current task is to create a TreeSet of Integers. I am supposed to create it in a way so the inner structure is hidden to the user, so I am supposed to declare as much as possible as private. In earlier exercises we were supposed to build the tree on our own in which case you could just set the Node Element as private which isn't required anymore now that I am allowed to use the Java utilities.
Currently it is looking like this:
import java.util.Iterator;
import java.util.TreeSet;
public class Tree28 {
public static void main(String[] args) {
TreeSet<Integer> Tree28 = new TreeSet();
for (int i = 0; i <= 10; i++) {
Tree28.add(new Integer(i));
}
//Testing duplicates (shouldn't add object as int=4 is already part of the collection)
Integer i11 = 4;
Tree28.add(i11);
System.out.println();
System.out.println("Printing TreeSet using For-Loop");
for (Integer i : Tree28) System.out.print(i + "\t");
System.out.println();
Iterator<Integer> it = Tree28.iterator();
System.out.println("Printing TreeSet using Iterator with While");
while (it.hasNext()) {
System.out.print(it.next() + "\t");
}
So the basic structure works and I understand it, but however it is not possible to set the Integer wrapper class as private and I couldn't find any solution using the search function. I'd highly appreciate if some of you could explain to me how I should proceed.
It sounds like the point of your assignment is to demonstrate encapsulation. As for the why to encapsulation, let's walk through it.
public class MySet {
final Set<Integer> mySet = new TreeSet<>(); //final, can't be reassigned
}
We can now create a MySet
object, which contains our java set:
MySet object = new MySet();
//assuming class is in the same package...
object.mySet.add(/* ... */);
object.mySet.remove(/* ... */);
//can't be done, it's final so it can't change! right?
object.mySet = null;
Of course, you can even add functionality around your set with methods. For the sake of demonstrating why you encapsulate, I've also added the method #wasAddedPreviously
and the field previous
public class MySet {
//...
final Set<Integer> previous = new TreeSet<>(); //for #wasAddedPreviously
public void add(int num) {
this.mySet.add(num);
this.previous.add(num);
}
public void printAll(PrintStream output) {
this.mySet.forEach(output::println);
}
public boolean wasAddedPreviously(int num) {
return this.previous.contains(num);
}
}
Obviously you can expose members like this, but you can also see how it the problems with public fields can get unweildly when you introduce complex state. Now, if you modify mySet
directly, you'll notice #wasAddedPreviously
breaks!
MySet object = new MySet();
object.mySet.add(42);
object.add(43);
object.printAll(System.out); //42, 43
object.mySet.remove(42);
object.mySet.remove(43);
object.wasAddedPreviously(42); //false
object.wasAddedPreviously(43); //true
To solve this, you try to make your object only expose and do exactly what you want to define that as. You don't want an object with all of the properties of a set inside, you want an object that can add, remove, or print everything, thus we cover that and ensure our fields aren't exposed (by using private
):
public class MySet {
private final Set<Integer> mySet = new TreeSet<>();
private final Set<Integer> previous = new TreeSet<>();
//added to allow removing from the set
public boolean remove(int num) {
this.mySet.remove(num);
}
}
From here, you won't be able to access object.mySet
anymore, but all of the functionality you require is there without the dangers of breaking your other methods:
MySet object = new MySet();
object.add(42);
object.add(43);
object.printAll(System.out); //42, 43
object.remove(42);
object.remove(43);
object.wasAddedPreviously(42); //true
object.wasAddedPreviously(43); //true
object.mySet./* ... */; // compile error
The added bonus is that when you're designing a larger system, instead of keeping track of lots of internal state (using an abstract two-set system for a specific problem?), you simply have the methods #add, #remove, #wasAddedPrev, and #print to deal with. This simplifies your own coding immensely.