Some knowledge points about containers and some codes

Posted by titeroy on Thu, 24 Feb 2022 10:09:23 +0100

generic paradigm

1. Introduction to generics:

1.1 basic concepts of generics:

1.2 benefits of generics:

Better code readability (no coercion); Program more secure

1.3 erasure type:

Type parameters written in generics during encoding will be removed by the compiler during compilation, which is called "type erasure"

2. Use of generics:

2.1 defining generics:

Generic characters can be any identifier, generally E,T,K,V,N,?

2.2 generic classes:

A generic class defines a generic type on a class. When users use the class, they define the type. The specific use method of generic class is to add one or more type parameter declarations after the class name, such as, < T, K, V >

2.2.1 grammatical structure

public class ***<Generic representation symbol>{

}

2.2.2 example

public class Generic <T>{
	private T flag;
	public void setFlag(T flag) {
		this.flag = flag;
	}
	public T getFlag() {
		return this.flag;
	}
}

public class Test {
	public static void main(String[] args) {
		Generic<String> generic = new Generic<>();
		generic.setFlag("admin");
		String flag = generic.getFlag();
		System.out.println(flag);
	}
}

2.3 generic interface:

Generic interfaces and generic classes are declared in the same way. The specific types of generic interfaces need to be declared in the implementation class.

2.3.1 grammatical structure:

public interface ***<Generic representation symbol>{

}

2.3.2 example

//generic interface 
public interface Igeneric<T> {
	T getName(T name);
}

//Interface implementation class
public class IgenericImpl implements Igeneric<String>{
	@Override
	public String getName(String name) {
		// TODO Auto-generated method stub
		return name;
	}
}

//Test class
public class Test2 {
	public static void main(String[] args) {
		IgenericImpl igeneric = new IgenericImpl();
		String name = igeneric.getName("JioH");
		System.out.println(name);
		
		Igeneric<String> igeneric2 = new IgenericImpl();
		String name2 = igeneric2.getName("JioH");
		System.out.println(name2);
	}
}

2.4 generic methods:

2.4.1 non static method

2.4.1.1 grammatical structure
public <Generic representation symbol> void  getName(Generic representation symbol name){
    
}

public <Generic representation symbol> Generic representation symbol  getName(Generic representation symbol name){
    
}
2.4.1.2 example:
public class MethodGeneric {
    //No return value
	public<T> void setName(T name) {
		System.out.println(name);
	}
    //There is a return value
    public<T> T getName(T name) {
		return name;
	}
}

public class Test3 {
	public static void main(String[] args) {
		MethodGeneric mg = new MethodGeneric();
		mg.setName("JioH");
		mg.setName(951933);
		
		MethodGeneric mg1 = new MethodGeneric();
		String name = mg1.getName("JioH");
		System.out.println(name);
		Integer name1 = mg1.getName(951933);
		System.out.println(name1);
	}
}

2.4.2 static method:

Static methods cannot access generics on a class

Generics can only be defined on methods

2.4.2.1 grammatical structure:
public static<Generic representation symbol> void  getName(Generic representation symbol name){
    
}

public static<Generic representation symbol> Generic representation symbol  getName(Generic representation symbol name){
    
}
2.4.2.2 example:
public class MethodGeneric {
    //No return value
	public static <T> void getFlag(T flag) {
		System.out.println(flag);
	}
    //There is a return value
	public static <T> T setFlag(T flag) {
		return flag;
	}
}

public class Test4{
    public static void main(String[] args) {
		//Static methods do not need to be instantiated and can be called directly with the class name
		MethodGeneric.setFlag("JioH");
		MethodGeneric.setFlag(123123);
		
		String flag = MethodGeneric.getFlag("jioh");
		Integer flag1 = MethodGeneric.getFlag(123123);
		System.out.println(flag);
		System.out.println(flag1);
	}
}

2.4.3 generic methods and variable parameters

In generic methods, generics can also define variable parameter types

2.4.3.1 grammatical structure
public <Generic representation symbol> void showMsg(Generic representation symbol... args){

}
2.4.3.2 example
public <T> void method(T...args) {
		//Traversal array
		for(T t:args) {
			System.out.println(t);
		}
	}
public class Test5{
    public static void main(String[] args) {
		//instantiation 
		MethodGeneric mg = new MethodGeneric();
		String[] arr = new String[] {"a","b","c"};
		mg.method(arr);
		Integer[] arr2 = new Integer[] {1,2,3};
		mg.method(arr2);
	}
}

2.5 wildcards and upper and lower restrictions:

Can only be used in < >

2.5.1 unbounded wildcards

2.5.1.1 grammatical structure:
public void showFlag(Generic<?> generic){

}
2.5.1.2 example:
public class Generic <T>{
	private T flag;
	public void setFlag(T flag) {
		this.flag = flag;
	}
	public T getFlag() {
		return this.flag;
	}
}

public class ShowMsg {
    public void showFlag(Generic<?> generic){
        System.out.println(generic.getFlag());
    }
}

public class Test6 {
    public static void main(String[] args) {
        ShowMsg showMsg = new ShowMsg();
        Generic<Integer> generic = new Generic<>();
        generic.setFlag(20);
        showMsg.showFlag(generic);
        
        Generic<Number> generic1 = new Generic<>();
        generic1.setFlag(50);
        showMsg.showFlag(generic1);
        
        Generic<String> generic2 = new Generic<>();
        generic2.setFlag("JioH");
        showMsg.showFlag(generic2);
    }
}

2.5.2 upper limit of wildcard

The upper limit limit indicates that the type of wildcard is t class and subclass of t class or T interface and sub interface of T interface; This method is also applicable to the upper limit of generics

2.5.2.1 grammatical structure
public void showFlag(Generic<? extends Number> generic){

}
2.5.2.2 example:
public class ShowMsg {
    public void showFlag(Generic<? extends Number> generic){
        System.out.println(generic.getFlag());
    }
}

2.5.3 lower limit of wildcard

The lower limit limit indicates that the type of wildcard is t class and the parent class of t class or T interface and the parent interface of T interface; This method is not applicable to generic classes

2.5.3.1 grammatical structure
public void showFlag(Generic<? super Number> generic){

}
2.5.3.2 example:
public class ShowMsg {
    public void showFlag(Generic<? super Integer> generic){
        System.out.println(generic.getFlag());
    }
}

3 generic summary

1. Basic type cannot be used for generic Test t

2. Object T elm = new T() cannot be created through type parameter;

container

1. Structure of container

1.1 structure diagram

1.1.1 single instance set

Store data one by one

1.1.2 double case set

Data storage based on key and value structure

2. Use of singleton set

2.1 introduction to collection interface

Collection is the root interface of singleton collection, and its two sub interfaces are List and Set interfaces

2.2 abstract methods in collection interface

2.3 List interface

2.3.1 List interface features

Orderly and repeatable

2.3.2 common methods of list

2.4 ArrayList container class

ArrayList is the implementation class of the List interface. It is the concrete implementation of List storage feature.

The bottom layer of ArrayList is the storage realized by array. Features: high query efficiency, low addition and deletion efficiency, and unsafe thread

2.4.1 adding elements

public class ArrayListTest {
	public static void main(String[] args) {
		//Instantiate the ArrayList container
		List<String> list = new ArrayList<>();
		//Add element
		boolean flag = list.add("123");
		System.out.println(flag);
		list.add(1, "JioH");
	}
}

2.4.2 get elements

get

for(int i = 0;i<list.size();i++){
	System.out.println(list.get(i));
}

2.4.3 replacement elements

set

String val = list.set(0, "JioH");
System.out.println(val);
for(int i=0;i<list.size();i++) {
    System.out.println(list.get(i));
}

//Convert to object []
//Cast cannot be performed on a converted method call
Object[] arr = list.toArray();
for(int i=0;i<arr.length;i++){
    String str = (String)arr[i];
    System.out.println(str);
}

//Converts a singleton collection to an array of the specified type
//The type needs to refer to the type in the generic type
String[] arr2 = list.toArray(new String[list.size()]);
for(int i=0;i<arr2.length;i++){
    System.out.println(arr2[i]);
}

2.4.4 merging operation of containers

The collection cannot be empty. If it is empty, FALSE will be returned

		List<String> a = new ArrayList<>();
		a.add("a");
		a.add("b");
		a.add("c");
		List<String> b = new ArrayList<>();
		b.add("d");
		b.add("e");
		//a and b
		boolean flag5 = a.addAll(b);
		System.out.println(flag5);
		for(String str:a) {
			System.out.println(str);
		}

2.4.5 container intersection operation

boolean flag6 = a.retainAll(b);

2.4.6 differential operation of container

//Remove the elements of b in the set of a
boolean flag6 = a.removeAll(b);

2.4.7 source code analysis

2.4.7.1 ArrayList underlying storage mode

The bottom layer of ArrayList is the storage realized by array

2.5 Vector container

The bottom layer of Vector is implemented by array, which is thread safe and inefficient

2.5.1 use of vector

The use of Vector is the same as that of ArrayList. Both implement the List interface and implement the abstract methods in the List interface

public class VectorTest {
	public static void main(String[] args) {
		//Instantiate Vector
		List<String> v = new Vector<>();
		v.add("a");
		v.add("b");
		v.add("a");
		for(int i=0;i<v.size();i++) {
			System.out.println(v.get(i));
		}
		//iteration	
		for(String str:v) {
			System.out.println(str);
		}
	}
}

2.5.2 Stack container

Stack stack container is a subclass of Vector, which implements a standard last in first out stack.

2.5.2.1 method of operating stack

2.5.2.2 use of stack
public class StackTest {
	public static void main(String[] args) {
		//Instantiate stack container
		Stack<String> s = new Stack<>();
		//Add element to stack container
		s.push("a");
		s.push("b");
		s.push("c");
		
		System.out.println(s.empty()); //false
		
		//View stack top element
		System.out.println(s.peek());
		//Returns the position of the element in the stack container
		System.out.println(s.search("c"));
		//Returns 1, counting from the top of the stack
		//Remove the element from the container
		String s1 = s.pop();
		System.out.println(s1);
		String s2 = s.pop();
		System.out.println(s2);
		String s3 = s.pop();
		System.out.println(s3);
		
		System.out.println(s.empty()); //true
	}
}
2.5.2.3 use cases of stack
//Symmetry of matching symbols
public class StackTest {
	public static void main(String[] args) {
        StackTest stacktest = new StackTest();
		stacktest.symmetry();
	}
	public void symmetry() {
		String str = "...{...[...(...)...]...}..(...)..[..]...";
		//instantiation 
		Stack<String> stack = new Stack<>();
		boolean flag = true;
		
		for(int i = 0;i<str.length();i++) {
			char c = str.charAt(i);
			if(c == '{') {
				stack.push("}");
			}
			if(c == '[') {
				stack.push("]");
			}
			if(c == '(') {
				stack.push(")");
			}
			//Judge whether the symbols match
			if(c == '}' || c == ']' || c == ')') {
				if(stack.empty()) {
					flag = false;
					break;
				}
				String x = stack.pop();
				//Single string to character
				if(x.charAt(0) != c) {
					flag = false;
					break;
				}
			}
		}
		if(!stack.empty()) {
			flag = false;
		}
		System.out.println(flag);
	}

2.6 LinkedList container class

The underlying LinkedList uses bidirectional linked list to store. It is characterized by low query efficiency, high addition and deletion efficiency and unsafe thread.

LinkedList implements the List interface, so LinkedList has the storage characteristics of List (ordered and repeatable elements).

2.6.1 use of LinkedList

public class LinkedListTest {
	public static void main(String[] args) {
		//instantiation 
		List<String> list =  new LinkedList<>();
		//Add element
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("a");
		//Get element
		for(int i = 0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
		
	}
}

2.6.2 use of LinkedList (non List standard)

public class LinkedListTest {
	public static void main(String[] args) {
		//instantiation 
		LinkedList<String> linkedlist = new LinkedList<>();
		//Add an element in the first position
		linkedlist.addFirst("xixi");
		linkedlist.addFirst("haha");
		linkedlist.addFirst("xixihaha");
		for(String str:linkedlist) {
			System.out.println(str);
		}
		//Add element at last position
		linkedlist.addLast("No change");
		linkedlist.addLast("Gale");
		linkedlist.addLast("Hee hee");
		//Get the first element
		System.out.println(linkedlist.getFirst());
		//Get the last element
		System.out.println(linkedlist.getLast());
		//Remove first element
		linkedlist.removeFirst();
		//Remove last element
		linkedlist.removeLast();
		//An element pops up from the stack represented by this list, which is equivalent to removeFirst
		linkedlist.pop();
		//Pushing an element into the stack represented by this list is equivalent to addFirst
		linkedlist.push("Ha ha ha ha");
		boolean flag = linkedlist.isEmpty();
		System.out.println(flag);
	}
}

LinkedList 3.6 source code analysis

2.6.3.1 node type
    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
//Address of the previous node address of the element object address of the next node
2.6.3.2 member variables
	transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
2.6.3.3 adding elements
    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    /**
     * Links e as last element.
     */
	void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
2.6.3.4 adding elements at the beginning and end
2.6.3.4.1 addFirst
    /**
     * Inserts the specified element at the beginning of this list.
     *
     * @param e the element to add
     */
    public void addFirst(E e) {
        linkFirst(e);
    }
    /**
     * Links e as first element.
     */
    private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }
2.6.3.4.2 addLast
    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #add}.
     *
     * @param e the element to add
     */
    public void addLast(E e) {
        linkLast(e);
    }
    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
2.6.3.5 add elements at specified positions
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }
    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }
    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
2.6.3.6 get elements
    /**
     * Returns the element at the specified position in this list.
     *
     * @param index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
    private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    /**
     * Tells if the argument is the index of an existing element.
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }
    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

2.7 Set interface

Set inherits from the Collection, and the method is consistent with the Collection.

2.7.1 features

Disordered and unrepeatable.

Common implementation classes: HashSet, TreeSet, etc; HashSet is generally used

2.7.2 HashSet

HashSet is a collection without duplicate elements, and the order of elements is not guaranteed. Moreover, HashSet allows null elements. HashSet is implemented by hash algorithm, and the bottom layer is actually implemented by HashMap (HashSet is essentially a simplified version of HashMap). Therefore, the query efficiency and addition and deletion efficiency are relatively high.

2.7.2.1 principle of hash algorithm

Hash algorithm is also called hash algorithm.

2.7.3 use of HashSet

public class HashSetTest {
	public static void main(String[] args) {
		//Instantiate HashSet
		Set<String> set = new HashSet<>();
		//Add element
		set.add("a");
		set.add("b");
		set.add("c");
		//Get element. There is no index in the Set container, so there is no get(int index) method
		for(String str:set) {
			System.out.println(str);
		}
		//Delete element
		set.remove("a");
		//Returns the number of elements
		int size = set.size();	
		System.out.println(size);
	}
}

2.7.4 HashSet storage feature analysis

The sequence of elements is not guaranteed, there are no duplicate elements, and the thread is unsafe. null elements are allowed.

Disorder:

In HashSet, the bottom layer uses HashMap to store elements, and the bottom layer of HashMap uses array and linked list to store elements. When the elements are stored in the array, they are not stored in order or at random. Instead, the hash value of the elements (obtained by hash algorithm) is analyzed to determine the position of the elements in the array.

Do not repeat:

When the hash values of the two elements are calculated to obtain the same position in the array, the equals() method of the element will be called to judge whether the two elements are the same. If the elements are the same, the element will not be added. If not, the element will be saved using a one-way linked list.

2.7.5 storing custom objects through HashSet

2.7.5.1 creating Users object
public class Users {
	private String username;
	private int userage;
	
	public Users(String username,int userage) {
		this.username = username;
		this.userage = userage;
	}
	public Users() {
		
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + userage;
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Users other = (Users) obj;
		if (userage != other.userage)
			return false;
		if (username == null) {
			if (other.username != null)
				return false;
		} else if (!username.equals(other.username))
			return false;
		return true;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public int getUserage() {
		return userage;
	}
	public void setUserage(int userage) {
		this.userage = userage;
	}
	@Override
	public String toString() {
		return "Users [username=" + username + ", userage=" + userage + "]";
	}
}
2.7.5.2 storing Users object in HashSet
public class HashSetTest {
	public static void main(String[] args) {
		//Instantiate HashSet
		Set<Users> set = new HashSet<>();
		Users u1 = new Users("JioH",18);
		Users u2 = new Users("JioH",18);
		set.add(u1);
		set.add(u2);
		for(Users users:set) {
			System.out.println(users);
		}
	}
}

2.7.6 TreeSet containers

TreeSet is a container that can sort elements. The bottom layer is actually implemented using TreeMap. A simplified version of TreeMap is maintained internally, and the elements of Set are stored through key. TreeSet needs to sort the stored elements internally, so we need to give a sorting rule

Implementation method of sorting rule:

The comparison rule is implemented by the element itself.

Specify the comparison rule through the comparator.

2.7.6.1 use of TreeSet
public class TreeSetTest {
	public static void main(String[] args) {
		//instantiation 
		Set<String> set = new TreeSet<>();
		//Add element
		set.add("a");
		set.add("d");
		set.add("b");
		set.add("a");
		for(String str:set) {
			System.out.println(str);
		}
	}
}

2.7.7 implement comparison rules through elements themselves

2.7.7.1 create Users class
public class Users implements Comparable<Users>{
	private String username;
	private int userage;
	
	public Users(String username,int userage) {
		this.username = username;
		this.userage = userage;
	}
	public Users() {
		
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + userage;
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Users other = (Users) obj;
		if (userage != other.userage)
			return false;
		if (username == null) {
			if (other.username != null)
				return false;
		} else if (!username.equals(other.username))
			return false;
		return true;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public int getUserage() {
		return userage;
	}
	public void setUserage(int userage) {
		this.userage = userage;
	}
	@Override
	public String toString() {
		return "Users [username=" + username + ", userage=" + userage + "]";
	}
	//Define comparison rules
	@Override
	public int compareTo(Users o) {
		if(this.userage < o.getUserage()) {
			return 1;
		}
		if(this.userage == o.getUserage()) {
			return this.username.compareTo(o.getUsername()); //Compare names
		}
		// TODO Auto-generated method stub
		return -1;
	}
}
2.7.7.2 store Users object in TreeSet
public class TreeSetTest {
	public static void main(String[] args) {
		//instantiation 
		Set<Users> set = new TreeSet<>();
		Users u = new Users("JioH",18);
		Users u1 = new Users("xixihaha",20);
		Users u2 = new Users("axixihaha",20);
		set.add(u);
		set.add(u1);
		set.add(u2);
		for(Users Users:set) {
			System.out.println(Users);
		}
	}
}

2.7.8 comparison rules realized by comparator

When defining comparison rules through a Comparator, we need to create a Comparator separately. The Comparator needs to implement the compare method in the Comparator interface to define comparison rules. When instantiating TreeSet, the Comparator object is handed over to TreeSet to complete the sorting of elements. At this point, the element itself does not need to implement the comparison rules.

2.7.8.1 create comparator
public class StudentComparator implements Comparator<Student>{
	//Define comparison rules	
	@Override
	public int compare(Student o1, Student o2) {
		// TODO Auto-generated method stub
		if(o1.getAge() > o2.getAge()) {
			return 1;
		}
		if(o1.getAge() == o2.getAge()) {
			return o1.getName().compareTo(o2.getName());
		}
		return -1;
	}
}
2.7.8.2 create Student object
public class Student {
	private String name;
	private int age;
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	
}
2.7.8.3 storing Users object in TreeSet
public class TreeSetTest {
	public static void main(String[] args) {
		//instantiation 
		Set<Student> set = new TreeSet<>(new StudentComparator());
		Student s = new Student("JIOH",18);
		Student s1 = new Student("jioh",16);
		Student s2 = new Student("JioH",22);
		set.add(s);
		set.add(s1);
		set.add(s2);
		for(Student str:set) {
			System.out.println(str);
		}
	}
}

Topics: Java Container