我的第一篇博客|JAVA集框架# JAVA集合(待续)

JAVA集框架# JAVA集合

分为四个部分:

  • 集合框架体系
  • Collection
  • Map
  • Collections

一、集合框架体系

java集合类非常多,主要分为两类,Collection和Map。
先来看Collection接口:它继承了Iterable接口,并分出了list和set接口,而Iterable有迭代器的作用,可以用来遍历Collection
单列集合:单个单个的元素
在这里插入图片描述

list:ArrayList、LinkedList、Vector;
set:HashSet、TreeSet
接下来是Map:
双列集合:键值对存放
在这里插入图片描述

Map:HashTable、HashMap、TreeMap

二、Collection

Collection方法(todo)

1.Interator接口的方法

可以用来遍历Collection的实现类
hasNext():可以用来判断是否还有下一个元素,返回true和false
next():下移一次指针,返回元素
在这里插入图片描述

  • 提示:在调用Interator.next()之前,一定要先进行Interator.hasNext()判断,否则会抛出异常。
    这是一个Arrays.sort方法的例子:
    需要记住的是,这个方法只能对数组使用,不能对ArraysList等使用,因为他们是一个对象。
Book[] books=new Book[3];
books[0]=new Book(20.1,"金瓶梅");
books[1]=new Book(100.2,"红楼们");
books[2]=new Book(90.2,"唐诗三百首");
Arrays.sort(books, new Comparator<Book>() {    
@Override   
public int compare(Book o1, Book o2) {       
Book book1=(Book)o1;        
Book book2=(Book)o2;        
double val=book1.price-book2.price;        
if(val>0){            
return 1;        }else if(val<0){            
return -1;        }else{            
return 0;        }   
}});
System.out.println(Arrays.toString(books));

接下来才是Iterator使用案例:

Collection books=new ArrayList();
books.add(new Book(90.2,"hongloum"));
books.add(new Book(100.2,"javabinan"));
books.add(new Book(200.2,"computer"));
Iterator iterator=books.iterator();
while (iterator.hasNext()) {    
Object next =  iterator.next();   
System.out.println(next);
}

2、用增强版for遍历Collection

for (Obiect obj: books){
sout(obj);
}
本质上就是底层简化的Iterator迭代器。

3、List接口和常用方法

list集合存放有序元素,并且每一个元素都有自己对应的索引值,元素可重复。

①常用方法:
  • void add(int index,Object object);
    向集合中的指定index位置插入object。其中一个重载函数void add(Object object),可以直接插入元素。
  • boolean addAll(int index,Collection col);
    把col中的元素一个一个全部插入index位置以及后面。
  • int get(int index)
    返回索引值
  • int indexof(Object obj);
    返回第一次出现这个元素的索引
  • int lastindexof(Object obj)
    返回最后一个元素索引
  • Object remove(int index);
    删除索引为index的元素,并且返回此元素
  • Object set(int index,Object object)
    设置新元素
②List的三种遍历
  • 利用迭代器Interator遍历,前面有示例代码
  • for-each
  • 普通for

4、ArraysList

注意事项:

  • 可以放所有元素,甚至放空元素
  • 基于数组实现的数据存储
  • 和Vector差不多,但是ArraysL是线程不安全的,在多线程时,不建议使用它,但是使用效率却高。
①扩容机制
  • ArraysList里面中维护了一个Object类型elementData里面
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HwtJKvlg-1624975374310)(en-resource://database/926:1)]
  • 当使用无参构造时,默认容量为0,第一次添加时会扩容为10,往后每次扩容为1.5
  • 如果使用指定大小的构造器,则每次扩容直接变为1.5倍。new ArraysList(int)

扩容机制源码分析:先写一个测试程序,然后debug看其扩容机制

 ArraysList list=new ArrayList();
 
 for(int i=0;i<10;i++)
 {
 list.add(i);
 }
 
 for(int i=0;i<100;i++)
 {
 list.add(i);
 }

调用无参构造源码解析在下图
在这里插入图片描述

扩容机制完成之后,就不断回调。回到最初的add函数,添加完毕之后,扩容添加的操作也就完成了。可以看出,这一番操作下来,每一次添加之前,都需要进行扩容判断,所以会造成一定的负担。
需要掌握的不是这个源码,而是如何利用debug观看和学习源码。这里调用有参构造的源码不再赘述。

5、Vector

Vector的基本介绍:

  • 底层也是Object[] elementDate数组;
  • 是线程安全的,方法有synchronized约束同步;
  • 在开发时,如果需要保证线程同步,可以使用Vector;
①扩容机制
ArraysListVector
底层是数组底层是数组
线程不安全但是效率高线程安全但是效率低
i.无参构造时,容量为10,往后1.5倍扩容;ii.有参构造时,往后直接1.5倍扩容i.无参构造时,容量为10,往后2倍扩容;ii.有参构造时,往后直接2倍扩容
②底层源码

还是一样的先写一段测试代码:

 Vector vector=new Vector();//打上断点
        for(int i=0;i<10;i++)
        {
            vector.add(i);
        }

debug之后可以发现,不管是有参还是五参数,都会进入一个有参构造函数中,默认值为10。然后进行和ArraysList相同的add操作,先判断是否装满了,如果没有装满,则扩容,然后再添加。

6、LinkedList

LinkedList的基本介绍:

  • 底层实现了双端链表和双端队列;
  • 可以添加任意元素,甚至null;
  • 同样是线程不安全的;
①底层构造

LinkedList对象里主要维护了三个属性:

  • size:长度
  • first:第一个节点
  • last:第二个节点
    在这里插入图片描述

每个节点中又维护了三个属性:

  • item:此节点存放的数据对象
  • next:下一个节点
  • prev:上一个节点
    在这里插入图片描述
②双向链表的增删改查


到这里,Collection中的List部分也就基本介绍完了,接下来是另一个继承了Collection接口的Set接口部分。

7、Set接口及其常用方法

set的基本介绍:

  • 继承了Collection接口
  • 里面存放的元素是无序的,每一个元素只能存放一次,如果存入相同元素,则会直接忽略,可以存入null,但是只能存放一次
  • 输出无序,但是却是一定的,不会因为两次编译和运行而改变。
①Set的遍历

和List的遍历稍有区别。因为Set是没有所以的,所以不能用一般的for循环来遍历。因为Set继承了interable接口,所以可以使用迭代器来进行遍历:
i.interator
ii.for(Object obj: set)

8、HashSet

HashSet的基本介绍:
是Set接口的一个实现类,底层是HashMap,其他属性继承了Set接口。

①不可重复元素再理解

不重复元素,实际上指的是不同的对象。来看下面的例子

Set set=new HashSet();
//1
sout(set.add("wenshuai"));//T
sout(set add("wenshuai"));//F
//2
sout(set.add(new Dog("wang")));//T
sout(set.add(new Dog("wang")));//T
//3
sout(set.add(new String("haixia")));//T
sout(set.add(new String("haixia")));//F

为什么会产生上述结果?
1.对于直接申请的String字符串,首先会在常量池中寻找,有则直接引用,没有则想常量池中添加再引用。因此第二个String创建时,常量池中已经存在wenshuai,所以二者创建的是同一个对象。因此第二个不能添加。
2.通过new出来的一般都是两个不同的对象,只是这两个对象里面的属性相同而已。
3.按理来说,这两个不是同一个对象,但是第二个却无法添加。原因和HashSet底层源码有关,存疑(todo)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值