package cn.itcast.set;
import java.util.HashSet;
import java.util.Set;
/*
集合的体系:
--------|Collection 单例集合的根接口
------------|List 如果实现了List接口的集合类,具备的特点:有序,可重复
---------------|ArrayList ArrayList底层是维护了一个Object数组实现的,特点:查询速度快,增删慢
什么时候使用Arraylist:如果目前的数据是查询比较多,增删比较少的时候,那么就使用Arraylist存储着批数据:比如高校的图书馆
---------------|LinkedList 底层是使用了链表数据结构实现的,特点:查询慢,增删块快
---------------|Vector(了解即可)底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低
------------|Set 如果实现了set接口的集合类,具备的特点:无序,不可重复
无序:添加元素的顺序与元素出来的顺序是不一致的
*/
public class Demo1 {
public static void main(String[] args) {
Set set = new HashSet();
set.add("王五");
set.add("李四");
set.add("张三");
System.out.println("添加成功么?"+set.add("李四"));
System.out.println(set);
}
}
package cn.itcast.set;
import java.util.HashSet;
/*
集合的体系:
--------|Collection 单例集合的根接口
------------|List 如果实现了List接口的集合类,具备的特点:有序,可重复
---------------|ArrayList ArrayList底层是维护了一个Object数组实现的,特点:查询速度快,增删慢
什么时候使用Arraylist:如果目前的数据是查询比较多,增删比较少的时候,那么就使用Arraylist存储着批数据:比如高校的图书馆
---------------|LinkedList 底层是使用了链表数据结构实现的,特点:查询慢,增删块快
---------------|Vector(了解即可)底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低
------------|Set 如果实现了set接口的集合类,具备的特点:无序,不可重复
-----------------|HashSet 底层是使用了哈希表来支持的,特点:存取速度快
-----------------|TreeSet
哈希表的其中一个特点:桶式结构(一个位置可以存放多个元素的)。
HashSet的实现原理:
往HashSet添加元素的时候,HashSet会先调用元素的hashcode方法得到元素的哈希值,
然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置。
情况1:如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置。
情况2:如果算出该元素的存储位置目前已经存在其他元素了,那么会调用该元素的equals方法与该位置的元素再比较一次
,如果equals返回的是true,那么该元素与这个位置上的元素视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行添加。
*/
class Person{
int id;
String name;
public Person(int id,String name){
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "{编号:"+this.id +this.name +"}";
}
@Override
public int hashCode() {
System.out.println("====hashcode方法调用了=====");
return this.id;
}
@Override
public boolean equals(Object obj) {
System.out.println("====equals方法调用了=====");
Person p = (Person)obj;
return this.id ==p.id ;
}
}
public class Demo2 {
public static void main(String[] args) {
/*
HashSet set = new HashSet();
set.add("狗娃");
set.add("狗剩");
set.add("铁蛋");
System.out.println("集合的元素:"+set);
*/
HashSet set = new HashSet();
set.add(new Person(110,"狗娃"));
set.add(new Person(220,"狗升"));
set.add(new Person(330,"铁蛋"));
//在现实生活中只要编号一致就为同一个人 Hashcode方法被调用4次,equals方法被调用1次
System.out.println("添加成功么?"+set.add(new Person(110,"狗娃")));
System.out .println("集合的元素"+set);
}
}
package cn.itcast.set;
/*
需求:接受键盘录入用户名和密码,如果用户名已经存在集合中,那么就是视为重复元素,不允许添加到HashSet中。
*/
import java.util.HashSet;
import java.util.Scanner;
class User{
String userName;
String password;
public User(String userName, String password) {
super();
this.userName = userName;
this.password = password;
}
@Override
public String toString() {
return "{ 用户名:"+this.userName+" 密码:"+ this.password+"}";
}
@Override
public boolean equals(Object obj) {
User user = (User)obj;
return this.userName.equals(user.userName)&&this.password.equals(user.password);
}
@Override
public int hashCode() { // abc 123 , 123 abc
return userName.hashCode()+password.hashCode();
}
}
public class Demo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashSet set = new HashSet();
while(true){
System.out.println("请输入用户名:");
String userName = scanner.next();
System.out.println("请输入密码:");
String password = scanner.next();
//创建一个对象
User user = new User(userName, password);
if(set.add(user)){
System.out.println("注册成功...");
System.out.println("当前的用户有:"+ set);
}else{
System.out.println("注册失败...");
}
}
}
}
package cn.itcast.set;
public class Demo4 {
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
System.out.println("两个是同一个对象吗?"+(str1 == str2));
System.out.println("str1的hashCode:"+str1.hashCode());
System.out.println("str2的hashCode:"+str2.hashCode());
/*
HashCode默认情况下表示的是没存地址,String类已经重写了Object类的HashCode方法
注意:如果两个字符串的内容一致,那么返回的hashcode码肯定也一致
*/
}
}
package cn.itcast.set;
import java.util.TreeSet;
/*
集合的体系:
--------|Collection 单例集合的根接口
------------|List 如果实现了List接口的集合类,具备的特点:有序,可重复
---------------|ArrayList ArrayList底层是维护了一个Object数组实现的,特点:查询速度快,增删慢
什么时候使用Arraylist:如果目前的数据是查询比较多,增删比较少的时候,那么就使用Arraylist存储着批数据:比如高校的图书馆
---------------|LinkedList 底层是使用了链表数据结构实现的,特点:查询慢,增删块快
---------------|Vector(了解即可)底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低
------------|Set 如果实现了set接口的集合类,具备的特点:无序,不可重复
-----------------|HashSet 底层是使用了哈希表来支持的,特点:存取速度快
哈希表的其中一个特点:桶式结构(一个位置可以存放多个元素的)。
HashSet的实现原理:
往HashSet添加元素的时候,HashSet会先调用元素的hashcode方法得到元素的哈希值,
然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置。
情况1:如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置。
情况2:如果算出该元素的存储位置目前已经存在其他元素了,那么会调用该元素的equals方法与该位置的元素再比较一次
,如果equals返回的是true,那么该元素与这个位置上的元素视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行添加。
-----------------|TreeSet 如果元素具备自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储
*/
public class Demo5 {
public static void main(String[] args) {
TreeSet tree = new TreeSet();
/*
tree.add(1);
tree.add(10);
tree.add(7);
tree.add(19);
tree.add(9);
*/
tree.add('b');
tree.add('f');
tree.add('a');
tree.add('c');
System.out.println(tree);
}
}
package cn.itcast.set;
import java.util.Comparator;
import java.util.TreeSet;
/*
treeSet添加自定义元素:
treeset要注意的事项:
1.往Treeset添加元素的时候,如果元素具备了自然顺序的特性,那么就按照自然顺序的特性排序。
2.往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现(comparable)接口,把元素的比较规则定义在compareTo(To)方法上。
3.如果比较元素的时候,compareTo方法返回的是0,那么该元素就被视为重复元素,不允许添加(注意:TreeSet与HashCode equals方法是没有任何关系的)
4.往TreeSet添加元素的时候,如果元素本身没有具备自然顺序的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。
5.往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口,在创建TreeSet对象的时候也传入了比较器,那么是以比较器的比较规则优先使用。
如何自定义比较器:自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可。
自定义比较器的格式:
class 类名 implements Comparator{
}
推荐使用:使用比较器(Comparator)
TreeSet的存储原理:底层是使用红黑树数(二叉树)据结构, 存储规则:左小右大
*/
class Emp //implements Comparable
{
int id;
String name;
int salary;
public Emp(int id,String name,int salary){
super();
this.id = id;
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return "{编号:"+this.id+"姓名:"+this.name+"薪水:"+this.salary+"}";
}
/*
@Override//元素元素之间的比较规则。
//负数,零或正整数,根据此对象是小于,等于还是大于指定对象。
public int compareTo(Object o) {
Emp e = (Emp)o;
System.out.println(this.name +"compare"+e.name);
return this.salary-e.salary;
}
*/
}
class MyComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Emp e1 = (Emp)o1;
Emp e2 = (Emp)o2;
return e1.id-e2.id;
}
}
public class Demo6 {
public static void main(String[] args) {
//创建一个比较器对象
MyComparator comparator = new MyComparator();
TreeSet tree =new TreeSet(comparator);
/*
tree.add(new Emp(113,"老钟",200));
tree.add(new Emp(110,"老陆",100));
tree.add(new Emp(220,"汤",300));
tree.add(new Emp(120,"老蔡",500));
tree.add(new Emp(320,"老黎",500));
*/
tree.add(new Emp(113,"老钟",100));
tree.add(new Emp(110,"老陆",200));
tree.add(new Emp(220,"汤",300));
tree.add(new Emp(120,"老蔡",500));
/*
老钟compare老钟
老陆compare老钟
汤compare老钟
汤compare老陆
老蔡compare老陆
老蔡compare汤
在二叉树中三个节点(根节点不算在其中)构成不了二叉树,自动调节节点
*/
System.out.println("集合的元素是:"+tree);
}
}
package cn.itcast.set;
import java.util.TreeSet;
/*
TreeSet是可以对字符串排序的,因为字符串已经实现了Comparable接口
字符串的比较规则:
情况一:对应位置上有不同的字符的出现,比较的就是对应位置上不同的字符
情况二:如果对应位置上的字符都一样,比较的是字符串的长度
将字符串的数值进行排序:
例如 String str="8 10 15 5 2 7" ----->"2 5 7 8 10 15"
*/
public class Demo7 {
public static void main(String[] args) {
TreeSet tree = new TreeSet();
/*tree.add("abc");
tree.add("abw");
tree.add("ab");
*/
System.out.println("abw".compareTo("abccccc"));
}
}
package cn.itcast.set;
import java.util.Iterator;
import java.util.TreeSet;
/*
需求:
将字符串的数值进行排序:
例如 String str="8 10 15 5 2 7" ----->"2 5 7 8 10 15"
*/
public class Demo8 {
public static void main(String[] args) {
String str="8 10 15 5 2 7";
String[] datas = str.split(" ");
TreeSet tree = new TreeSet();
for(int i = 0;i<datas.length;i++){
tree.add(Integer.parseInt(datas[i]));//字符串转int类型的数据是需要使用Integer.parseInt进行转换
}
//遍历treeset的元素拼接成对应的字符串
Iterator it = tree.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
}
}