个人博客网:https://wushaopei.github.io/ (你想要这里多有)
一、数组和集合
1、相同点:
数组 与 集合 都是内存中对数据进行存储和管理的“容器”
2、数组存储的特点和缺点
特点:
1.数组一旦创建成功,长度不可改变
2.元素存储的类型就是数组声明时的类型
缺点:
1.数组的长度不可变
2.数组的API属性比较少,比如没有 增、删、改、插 等.....
3. 存储的元素是有序的可重复的,对无序的不可重复的无能为力
3、集合存储的特点
1.长度可变
2.底层的数据结构比较丰富。比如:数组,链表,红黑树
3.集合的API比较丰富,比如 增 ,删,改 ,查,插等.......
4.对数据的存储方式支持也比较多,比如有序可重复,无序不可重复
二、集合概述
1、集合的体系分类
2、Collection 接口继承树
3、Map接口继承树
三、Collection 接口
1、Collection 接口 定义
Collection 接口是 List 、Set 和 Queue接口的父接口,该接口里定义的方法既可以用于操作Set集合,也可以用于操作List 和Queue集合。
由于JDK 不提供此接口的任何直接实现,而是提供更具体的子接口(如: Set 和 List )实现。
注意:
在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型。
2、Collection 接口常用方法
3、遍历Collection 的两种方式:
3.1 Iterator 迭代器接口
(1)作用: 通过指针的方式遍历集合元素
实现: java.utils 报下定义的迭代器接口: Iterator
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。
(2) 如何获取实例: 集合的对象. iterator()
(3) 常用方法:
hasNext() : 判断是否还有下一个元素
next(): ① 指针下移 ②返回指针指向的元素
(4) 案例实操:
public class IteartorTest {
@Test
public void test2(){
Collection c = new ArrayList();
c.add("aaa");
c.add("bbb");
c.add("ccc");
c.add("ddd");
c.add("eee");
/*
* 错误的写法 : 因为c.iterator()会创建一个新的对象
while(c.iterator().hasNext()){
System.out.println(c.iterator().next());
}
*/
/*
* 错误的写法:因为每次调用next()方法都会指针下移
Iterator iterator = c.iterator();
while(iterator.next() != null){
System.out.println(iterator.next());
}
*/
}
@Test
public void test(){
Collection c = new ArrayList();
c.add("aaa");
c.add("bbb");
c.add("ccc");
c.add("ddd");
c.add("eee");
//获取Iterator实现类的对象
Iterator iterator = c.iterator();
//next() ①指针下移 ②返回指针指向的元素
// Object obj = iterator.next();
// System.out.println(obj);
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
//如果没有下一个元素则会报异常
// System.out.println(iterator.next());
//不建议这么写
/*
System.out.println(iterator.next());
for (int i = 0; i < 5; i++) {
System.out.println(iterator.next());
}
*/
System.out.println(iterator.next());
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
(5) 原理图解:
注意:
在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。
(6)常用接口方法
3.2 增强 for 循环: (foreach 循环)
(1)格式
for(元素的类型 临时变量 : 集合、数组的对象){
}
注意:Java 5.0 提供了 foreach 循环迭代访问 Collection
(2)案例实操
Collection c = new ArrayList();
c.add("gg");
c.add("jj");
c.add("dd");
c.add("mm");
for(Object obj : c){
System.out.println(obj);
}
(3)遍历数组
/*
* 可以理解成
* 1. String str = names[0];
* 2. str = "aaa";
*/
String[] names = {"小泽泽","小圆圆","小玲玲"};
for(String str : names){
System.out.println(str);
}
4、Collection 子接口-List 接口
(1)List 接口 定义 :
* Java中数组用来存储数据的局限性
* List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
* List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
* JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。
存储的数据特点: 存储的元素是有序的且可重复的 (由其底层数据结构可知原因)
(2)List 集合里 用于 根据索引来操作集合元素的方法
- void add(int index, Object ele)
- boolean addAll(int index, Collection eles)
- Object get(int index)
- int indexOf(Object obj)
- int lastIndexOf(Object obj)
- Object remove(int index)
- Object set(int index, Object ele)
- List subList(int fromIndex, int toIndex)
将当前集合中fromIndex到toIndex位置上的所有元素存放到一个新的集合中 [fromIndex,toIndex)
(3)常用实现类:
|-------ArrayList : 主要实现类
|-------LinkedList :
|-------Vector
(4)实现类之 : ArrayList
① 底层原理:
a. List的主要实现类底层是一个数组,查找快,增删慢。线程不安全的效率高。List的主要实现类底层是一个数组,查找 快,增删慢。线程不安全的效率高。
b. 当我们创建一个空参构造器的ArrayList的对象时,底层会为我们创建一个长度为10的数组,当我们向容器中添加
c. 第11个元素时,底层会进行扩容,扩容为原来的1.5倍(创建一个长度为原来的1.5倍的数组,同时将原有的数据复制到新的数组中)。
注意:
Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合
②构造器说明:
new ArrayList() : 底层创建一个长度为10的数组
new ArrayList(int initialCapacity) : 创建一个长度为initialCapacity的数组
③案例实操:
@Test public void test2(){ LinkedList list = new LinkedList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); // list.addFirst("AAA"); Object obj = list.removeFirst(); System.out.println(list); // System.out.println(list.getFirst()); System.out.println(obj); }
④ 存储的元素的要求 : 往集合中添加自定义对象的数据时,自定义类必须重写equals
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) 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;
}
/*
* 注意:往集合中添加自定义对象的数据时,自定义类必须重写equals
*/
@Test
public void test(){
Collection c = new ArrayList();
c.add("aaa");
c.add(123);
c.add("ccc");
c.add(new Person("aa",18));
//remove(Object o) : 将o从当前集合中删除掉,删除成功返回true,否则返回false
// boolean remove = c.remove("aaa");
// remove = c.remove(new Person("aa",18));
//removeAll(Collection c): 从当前集合中删除和c集合交集的部分(c和c2相同的数据)。
Collection c2 = new ArrayList();
c2.add("aaa");
c2.add(123);
c2.add(555);
c.removeAll(c2);
System.out.println(c);
}
(5)实现类之 : LinkedList
① 作用:对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
② 常用方法:
void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()
5、List 面试题
[面试题]ArrayList,LinkedList,Vector的区别是什么?
三者都是List的实现类,存储的元素都是有有序的可重复的。
ArrayList : List的主要实现类底层是一个数组,查找快,增删慢。线程不安全的效率高。
LinkedList : 底层是一个双向链表,查找慢,增删快
Vector :古老的实现类,底层是一个数组,查找快,增删慢。线程安全的效率低。
(1)ArrayList 面试题
① 思考?ArrayList到底是根据索引去删除,还是删除的是内容
/*
* 面试题
*/
@Test
public void test3(){
List list = new ArrayList();
list.add("aa");
list.add(111);
list.add(1);
//根据索引值删除内容
// Object remove = list.remove(1); //思考?到底是根据索引去删除,还是删除的是内容
//删除内容1
list.remove(new Integer(1));
System.out.println(list);
}
② ArrayList的底层实现?
当我们创建一个空参构造器的ArrayList的对象时,底层会为我们创建一个长度为10的数组,当我们向容器中添加
第11个元素时,底层会进行扩容,扩容为原来的1.5倍(创建一个长度为原来的1.5倍的数组,同时将原有的数据复制到新的数组中)。