当前位置: 代码迷 >> 综合 >> JAVA基础整理(迭代器,Set集合 TreeSet)
  详细解决方案

JAVA基础整理(迭代器,Set集合 TreeSet)

热度:28   发布时间:2023-12-18 17:07:25.0

如何遍历list

JDK1.7之前底层有一个大小为10的空数组,但是用的无参数,集合中没有元素,所以size为0

JDK1.8 之后提供了优化,不会创建一个10大小的数组,调用add函数,开始开辟堆空间,即数组大小

普通for循环 for(;?

增强for循环 (底层就是使用的迭代器实现,所以只能打印,不能赋值)

for(object e:list){
    system.out.println(e);
}

迭代器遍历

hasNext会把指针向下移动来判断下一个是否有值

hasNext()判断迭代器中是否还有下一个元素 有ture
next() 获取上一个元素
remove() 迭代器中的删除方法,删除会同步到集合中,切记绝对不能在迭代器中使用集合对象删除元素,因为无法同步给迭代器对象
Iterator it = list.iterator();
while(it.hasNext()){
    system.out.println(it.next());//迭代器中禁止使用集合对象删除集合中的元素,只能使用迭代器的方法删除
}
for(Iterator its = list.iterator();its.hasNext;){
    system.out.println(it.next());
}

当前没有Iterator的时候,迭代器使用Enumeration——这个只适用于Vector(了解)

Vector v = new Vector();
v.addAll(list);
//迭代遍历
Enumeration elements = v.elements(); //需要判断是否还有下一个元素 
while(elements.hasMoreElements()) {
    //取值 System.out.println(elements.nextElement());
}

基础器迭代器有一个子类,比基础迭代器更加强大 ListIterator,提供了多个方法

在这里插入图片描述

ListIterator Iter = list.listIterator(); 
while(Iter.hasNext()) {
    //是否还有下一个元素 System.out.println(Iter.next());
}
//需要获取的指针在最后一个位置即遍历的时候遍历到集合的末尾 //当前迭代器中提供了向上遍历的方式 
while(Iter.hasPrevious()) {
    //是否还有上一个元素System.out.println(Iter.previous());//获取元素值
}

LinkedList提供了一个特有的迭代器 descendingIterator (降序迭代器)

//使用方式和基础迭代器一样 linkedlist专有
Iterator descendingIterator = list.descendingIterator();
while(descendingIterator.hasNext()) {
    System.out.println(descendingIterator.next());    
}
迭代器异常问题

并非迭代异常

Iterator it = list.iterator(); //遍历迭代器对象,判断是否是否还有下一个元素 
while(it.hasNext()) {
    
//通过迭代器对象获取集合中元素,但是集合中的元素的类型是Object类型,需要进行对象的向下转型 String str = (String)it.next();if(str.equals("A")) {
     //在迭代器中绝对禁止使用集合对象删除集合中元素,只能使用得带器中带有的方法才可删除 //list.remove("C");//需要使用迭代器对象中方法删除it.remove();} 
}

基本上ArrayList采用size属性来维护自已的状态,而Iterator采用cursor来来维护自已的状态。

当size出现变化时,cursor并不一定能够得到同步,除非这种变化是Iterator主动导致的。

从上面的代码可以看到当Iterator.remove方法导致ArrayList列表发生变化时,他会更新cursor来同步这一变化。但其他方式导致的ArrayList变化,Iterator是无法感知的。ArrayList自然也不会主动通知Iterator们,那将是一个繁重的工作。Iterator到底还是做了努力:为了防止状态不一致可能引发的无法设想的后果,Iterator会经常做checkForComodification检查,以防有变。如果有变,则以异常抛出,所以就出现了上面的异常。

set集合

set是collection集合的子接口,无序,排除重复,set集合中主要使用Hash算法

(HashSet集合—>>子类LinkedHashSet集合 TreeSet集合)

Hash也称散列,为了快速存取角度设计,空间置换—空间换时间, hash的组成是一种线性表(数组+链表)

散列表,是根据键值对映射关系记录储存的位置,加快查找,这个映射就是“散列函数”存放记录的位置就叫做“散

列表”

同义词:因为存储数据在散列列表中,会存在一个问题,即两个元素通过散列函数计算的地址相同,那么这两个元素就是同义词

散列函数计算的机构会存储到一个具体的单元,称为“”。桶的范围就是从0到-1

如何存储到hash表

hash表是数组+链表的形式实现,数组作为位置存在,链表作为具体值存储

散列函数----hash(key)%len—计算出位置

在这里插入图片描述

扩容问题

java中散列表单元大小都是2的幂,初始大小为16(即2的4次幂)系统提供的加载(负载)因子是0.75,当存的数据达到加载因子的时候(即16*0.75 = 12),此时hashSet将会重新计算散列表,将里面原有的散列结构全部抛弃,重新开辟一个散列空间32(即2的5次幂),此时会重新计算所有数据并将数据重新存储,当前hash表扩容性能较低

ps:**加载因子:**存储70个元素,但是存70个元素申请了100个空间, 70 / 100 = 0.7 这个数字就是负载(加载)因子

TreeSet集合(排序)

TreeSet集合是一个自带排序的集合,也继承Set集合这边的排重功能。

JDK1.7之前用二叉树,JDK1.8之后使用是红黑二叉树(平衡二叉树)

linux系统就是树状态系统,

需要排序必须是相同数据类型,需要实现comparable接口—应对的是treeset无参构造方法

当前对象.属性-传入对象.属性==>升序

传入对象.属性-当前对象.属性==>降序

一般java中所提供的系统类包装类或者其他引用类型基本上都是先实现Comparable

list集合和set集合的父类 collection类,所以当Collection作为参数的时候可以接受一个list集合的实现类,也可以接受一个set集合的时候类

泛型

1.集合可以储存任何数据类型(引用类型),数据的数据类型是Object类型

作用:想规范集合储存数据,也就是在向集合储存数据的时候对其储存数据类型进行检查,使用泛型. 不是这个类型会报错

List<Integer> list =  new List();
//list储存不是Integer的类型会报错

2.设计一个点point,来封装坐标,需要支持String,Integer,Double,Float

class Point<T>{
    private T x;private T y;
}

占位符:本身没有意义,只是占位,只有给当前的占位符的位置赋值一个具体类型时它才会有真正的意义

泛型:可以达到一个通用型 通过<占位符>———在编译时期检查是否满足当前设计的数据类型

泛型是使用在编译阶段的,编译时期结束后生成的.class文件中不存在泛型

泛型应用

泛型作用在类上,创建类的时候动态的获取数据类型

//在类上定义的泛型可以应用在整个类体上
语法:访问权限修饰符 class 类名<占位符>{
    类体中就可以应用了
}占位符一般是被一个字母(26个英文字母大小(任意))
public class GenericityClass<T,M>{
    private T x;private T y;public GenericityClass(T x,T y){
    this.x = x;this.y = y;}public void show(T t){
     //泛型T作为方法的参数数据类型system.out.println(t);}public<E> E showInfo(E e){
    //占位符可以在方法的声明时使用,可以作为返回值return e;}//静态方法不能使用类所提供的泛型,因为static的优先级高,加载时泛型还没有public static<M> void display(M m){
    }
}public class test{
    public static void main(String args){
    GenericityClass<Integer> gc = new GenericityClass<Integer>(1,2);创建类的时候进行泛型赋值,此时给泛型赋值上了集体的数据类型GenericityClass<String> gc = new GenericityClass<String>("1","2");gc.showInfo = gc.showinfo(1);//会根据参数自动推断其数据类型}
}
泛型在接口上
public interface inte<T>{
    //T NAME = "nini"; 这里是不可以的,因为是静态常量void run(T t);default T getName(T t){
    return t;}static<E> void setName(E e){
    system.out.println(e);}
}
泛型限定

对传人的数据进行约束

<? extends 累> ?是通配符 作用可以代表数据类型 但这个数据类型会被后面的类说约束 #### Map集合 设A,B两个非空集合,如果存在一个法则f,使的A中内一个元素,按照法则f在b中有一个唯一的值对应
  相关解决方案