Java-集合-Set 基本数据类型-简单了解

  1. Set子接口:
    I. 特点:无序、无下标、元素不可重复(当插入新元素时,如果新元素与已有元素进行equals比较,结果为true时,则拒绝新元素的插入)
    II. 方法:全部继承自Collection中的方法
    一个不包含重复元素的col lection 。更确切的讲,不包含 e1.equals(e2)的元素对e1和e2,并且最多包含一个null元素。正如其名称所暗示的,此接口模仿了数学上的set抽象。
    在所有构造方法以及add、equals和hashCode方法协定上,Set接口还加入了其他规定,这些规定超出了从Collection接口所继承的内容。出于方便考虑,它还包括了其他继承方法的声明(这些声明的规范已经专门针对Set接口进行了修改,但是还没有任何其他的规定)。
    对这些构造方法的其他规定是(不要奇怪),所有构造方法必须创建一个不包括抽工夫元素的set(正如上面所定义的)。
    注:如果将可变对象作set元素,那么必须极其小心。如果对象是set中某个元素,以一种影响equals比较的方式改变对象的值,那么set的行为就是不确定的。此项禁止的一个特殊情况/是不允许某个set包含其自身作为元素。

  2. foreach循环:
    for(数据类型 变量名 : 容器名称){ //可遍历集合或数组(常用在无序集合上)
    }
    HashSet set = new HashSet();
    set.add(“A”);
    set.add(“B”);
    set.add(“C”);
    System.out.println(set.size());
    for(String str : set){
    System.out.println(str);
    }

  3. Set接口实现类:
    I. HashSet【重要】:
    此类实现Set接口,由哈希表(实际上是一个HashMap实例)支持,它不保证set的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。
    此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains和size,假定哈希函数将这些元素正确地分布在桶中。对此set进行迭代所需的时间与HashSet实例的大小(元素的数量)和底层HashMap实例(桶的数量)的“容量”的合成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
    注意:此实现不是同步的。如果多个线程同时访问一个哈希set,而其中至少一个线程修改了该set,那么它必须保持外部同步,这通常是通过对自然封装该set的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.zynchronizedSet方法来“包装”set。最好在创建时完成这一操作,以防止对该set进行意外的不同步访问。
    Set s = Collections. zynchronizedSet(new HashSet(…));

构造方法摘要:
HashSet() 构造一个新的空set,其底层HashMap实例的默认初始容量是16,加载因子是0.75。 加载因子–扩容依据 百分之75的扩容
HashSet(Collection<? extends E> c) 构造一个包含collection中的元素的新set
HashSet(int initialCapacity) 构造一个新的空 set,其底层HaspMap实例具有指定的初始容量和默认的加载因子(0.75)
HashSet(int initialCapacity, float loadFactor) 构造一个新的空set,其底层HaspMap实例具有指定的初始容量和指定的加载因子。

1). HashSet的底层使用的HashMap类,即是将所有需要存入HashSet的值,直接保存在HashMap中
2). HashSet如何去掉重复?
3). 先判断hashCode是否一致,==比较地址,equals比较内容

main(){
Student s1 = new Student(“Tom”,20,“男”,99D);
Student s2 = new Student(“jack”,24,“男”,94D);
Student s3 = new Student(“annie”,21,“女”,96D);
Student s4 = new Student(“marry”,19,“女”,100D);
Student s5 = new Student(“Tom”,20,“男”,99D);
HashSet students = new HashSet();
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
students.add(s4);//插入重复对象(地址相同)
students.add(s5);//插入重复对象(地址不同,内容相同)

for(Student stu : Students){
System.out.println(stu);
}
System.out.println(s1.equals(s5));
}
class Student{
String name;
Integer age;
String sex;
Double score;
public Student(){ super(); }
public Student(String name, Integer age, String sex, Double score){
super(); this.name = name; this.age= age; this.score =score;}
public String toString(){//打印属性
return “Student [name = “+name+”,age= “+ age +”,sex = “+sex”,score = “+score+”]”;
}

//重写hashCode 让 地址不同 内容相同的也能被排除在外
@Overrive
public int hashCode(){
renturn this.name.hashCode()+this.age.hashCode()+this.sex.hashCode()+this.score.hashCode();
}

//触发条件:两个对象的哈希码相同,才执行equals
@Override
public Boolean equals(Object obj){
System.out.println(“—Student equals() Exected–”);
if(this == obj) return true;
if(obj == null) return false;
if(this.getClass() != obj.getClass()) return false ’
Student s =(Student)obj;
if(this.name.equals(s.name) && this.age.equals(s.age)&&this.sex.equals(s.sex)&&this.score.equals(s.score))
return true;
return false;
}
}

问一:介绍一下set? set是collections的子类,无序,无序无下标,元素不可重复。
问二:hashset原理?
怎么过滤掉重复元素?
基于存入的对象的hashCode 相同的情况下,会调用equals进行确认,如果equals返回的结果为true,则排除后者。
equals本身就是==比较 怎么能比较出地址不相同内容相同的?
1.做内容的覆盖
2.覆盖HashCode
尽可能保证相同对象返回相同的HashCode
尽量保证不同对象返回不同HashCode

II. LinkedHashSet【了解】:
1).链表实现的HashSet,按照链表进行存储,即可以保留的插入顺序。
2).底层使用LinkedHashMap(链表结构)存储,节点形式单独存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素插入顺序
哈希表和相关的Set接口列表实现,具有可预测的迭代顺序。这不同于HashSet实施,它维护了一个链表贯穿其所有作品。这个链表定义迭代顺序,这是为了在该元素被插入到集合(插入顺序)。注意插入的顺序是不如果元素是重新插入进入设置的影响。(一元e重新插入到一套s如果s.add(e)时调用将返回true s.contains(e)立即调用。之前)
这个实现备件客户从指定,一般由HashSet混沌有序,又不增加成本与TreeSet。它可以被用来产生一个具有相同的顺序为原来的一组,无论原来的设置的实施:
void foo(集){集抄=新linkedhashset(S);…}
这种技术如果一个模块的输入,以一组份是特别有用的,后来返回结果的顺序是:确定的副本。(客户一般喜欢有东西返回的顺序一样了。)
这个类提供了所有可选的Set操作,并允许null元素。像HashSet,它的基本运算提供了稳定的性能(add,contains和remove),假设哈希函数的适当分散元素在水桶。性能可能会略低于HashSet,由于维护链表的附加费用,但有一个例外:在LinkedHashSet迭代需要的设置大小比例时,无论其能力。在HashSet迭代可能是昂贵的,需要时间来容量比例。
链接散列集有两个参数影响它的性能:初始容量和负载因子。他们是精确的定义为HashSet。注意,然而,选择初始能力值过高的惩罚是不太严重的这类HashSet相比,对于这类迭代次数不受力。
LinkedHashSet()
构造一个新的,空链接的哈希集,默认初始容量(16)和负载因子(0.75)。
LinkedHashSet(Collection<? extends E> c)
构造一个与指定集合相同的元素的新链接散列集。
LinkedHashSet(int initialCapacity)
构造一个新的、具有指定初始容量和默认负载因子(0.75)的空链接哈希集。
LinkedHashSet(int initialCapacity, float loadFactor)
构造一个具有指定初始容量和负载因子的新的空链接哈希集。

main(){
LinkedHashSet set = new LinkedHashSet();
set.add(“A”); set.add(“B”); set.add(“C”); set.add(“D”);
for(Object obj : set){//没加泛型都是object
System.out.ptintln(obj);
}
}//插入的顺序

III.TreeSet【了解】:
1). 实现了SortedSet接口,要求必须可以对元素排序。 基于排列顺序实现元素不重复
public interface SortedSet extends Set
一个 Set进一步提供了一个总序的元素。用他们的 natural ordering元素是有序的,或由 Comparator通常设置在设置创建时间排序。该集合的迭代器将遍历集合中的元素顺序。提供了一些额外的操作以利用排序。(此接口是 SortedMap。集模拟)
所有的元素插入排序集必须实现Comparable接口(或由指定的比较器接受)。此外,所有这些元素必须相互比较:e1.compareTo(e2)(或comparator.compare(e1, e2))必须不把任何一个元素e1和e2在排序集ClassCastException。企图违反此限制将导致犯罪的方法或构造函数调用扔ClassCastException。
所有通用的排序设置实现类应提供四个“标准”的构造函数:1)一个无效(无参数)构造函数,它创建一个空的排序集,根据其元素的自然顺序。2)一个带有一个参数的类型Comparator构造函数,它创建一个空的分类根据指定的比较器排序。3)一个带有一个参数的类型Collection构造函数,创建一个新的排序设置作为参数相同的元素,根据元素的自然顺序排序。4)一个带有一个参数的类型SortedSet构造函数,创建一个新的排序设置相同的元素和顺序输入排序设置相同。没有办法强制执行此建议,因为接口不能包含构造函数。

2). 所有插入元素,必须实现Comparable接口,覆盖compareTo方法。
3). 根据compareTo方法返回0作为去重的依据,(意味重复)

基于 TreeMap NavigableSet实施。用他们的 natural ordering元素是有序的,或由 Comparator在设定的创作时间,这取决于使用哪个构造函数。
这种实现提供保证日志(N)为基本操作的时间成本(add,remove和contains)。
注意:订购一套维护(是否提供一个明确的比较器)必须符合等于如果是正确执行Set接口。(见Comparable或Comparator为符合等于。精确的定义)这是因为Set接口在equals操作定义,但TreeSet实例执行所有的元素进行比较使用compareTo(或compare)方法,所以两元素被视为平等的方法是,从集合的角度,平等。一套是明确即使订货不等于行为;它只是不服从的Set接口一般合同。
构造方法:
TreeSet()
构造一个新的、空的树集,根据其元素的自然排序进行排序。
TreeSet(Collection<? extends E> c)
构造一个新的树集包含在指定集合的元素,根据其元素的自然排序排序。
TreeSet(Comparator<? super E> comparator)
构造一个新的、空的树集,根据指定的比较器进行排序。
TreeSet(SortedSet s)
构造一个包含相同元素的新树集,并使用相同的排序作为指定的排序集。

main(){
TreeSet set = new TreeSet();
set.add(“A”); set.add(“B”); set.add(“C”); set.add(“D”);
for(Object obj : set){
System.out.println(obj);
}
}//自动排序
//所谓的排序操作就是 就已经写好了,去访问你传入的这组对象,转型成接口类型并调用接口中的方法 XXX.comparaTo(XXX)方法
/
main(){
TreeSet< Teacher > teachers= new TreeSet< Teacher >();
teachers.add(new Teacher(“tom”,5000D));
teachers.add(new Teacher(“jack”,4000D));
teachers.add(new Teacher(“vicky”,3000D));
teachers.add(new Teacher(“eric”,6000D));
for(Teacher t : teachers){
System.out.println(t);
}
}
class Teacher{
String name;
Double salary;
public Teacher(String name,Double salary){
super();
this.name = name;
this.salary = salary;
}
@Override
public int comparaTo(Teacher o){
if(this.salary > o.salary){
return 1;
}else if(this.salary < o.salary){
return -1;
}
return 0; } ///若想加入依据重复但,其它内容不重复时,可以修改 return 1;
///若有多个元素,则可以从这继续判断元素
/
if(this.name.comparaTo(o.name) < 0){
return -1;
}else if(this.name.comparaTo(o.name) > 0){
return 1;
}else{
return this.sex.comparaTo(o.sex);
}


}
//但凡排序的依据或者比较的依据存在重复,就叫重复元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值