Java集合一
Java集合一
一、集合
1.1、集合的概述
编程的时候需要存储多个数据,使用长度固定的数组存储格式,不一定满足我们的需求,更适应不了变化的需求,那么此时我们就可以使用集合来做
- 集合类的特点:提供了一种存储空间可变的存储模型,存储的数据容量随时可以发生改变。
1.2、集合类的体系结构
- 以上都只是接口,都需要具体的实现类
- 这些出现的实现类是常用的,至于其他未出现的实现类,完全我们能够独立学习了解的。
二、Collection
2.1、Collection的概述
java.util
Interface Collection<E>
参数类型
E - 此集合中元素的类型
public interface Collection<E>
extends Iterable<E>
- Collection是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供Collection接口的任何直接实现:但它提供了更具体的子接口的实现,如
Set
和List
- 创建Collection集合对象
- 多态的方式
- 具体的实现类ArrayList
import java.util.ArrayList;
import java.util.Collection;
/* 创建Collection集合对象
* 多态的方式
* 具体的实现类ArrayList()
*/
public class collectiontest01 {
public static void main(String[] args) {
//创建Collection集合对象
Collection<String> collection = new ArrayList<String>();
//添加元素:boolean add(E e)
collection.add("Hello");
collection.add("first");
//输出对象
System.out.println(collection);//结果为[Hello, first]
}
}
2.2、Collection集合常用方法
add(添加元素)、remove(从集合中移除指定的元素)、clear(清空集合中的元素)、contains(判断集合中是否存在指定元素)、isEmpty(判断集合的是否为空)、size(输出集合中元素个数)
import java.util.ArrayList;
import java.util.Collection;
public class collectiontest02 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
//add方法:添加元素
c.add("add");
c.add("remove");
c.add("clear");
c.add("contains");
c.add("isEmpty");
c.add("size");
System.out.println(c);//结果为[add, remove, clear, contains, isEmpty, size]
//remove方法:从集合中移除指定的元素
// c.remove("remove");
// System.out.println(c);//结果为[add, clear, contains, isEmpty, size]
//clear:清空集合中的元素
// c.clear();
// System.out.println(c);//结果为[]
//contains:判断集合中是否存在指定元素
// System.out.println(c.contains("contains"));//结果为:true
// System.out.println(c.contains("Hello"));//结果为:false
//isEmpty:判断集合的是否为空
// System.out.println(c.isEmpty());//结果为:false
//size:输出集合中元素个数
// System.out.println(c.size());//结果为:6
}
}
2.3、Collection集合的遍历
- Iterator:迭代器,集合的专用遍历方式
- Iterator
iterator():返回此集合中元素的迭代器,通过集合的Iterator()方法得到 - 由于迭代器是通过集合的Iterator()方法得到的,所以它是依赖于集合存在的
java.util
Interface Iterator<E>
参数类型
E - 此迭代器返回的元素的类型
public interface Iterator<E>
迭代器有两种不同的枚举方式:
1、迭代器允许调用者在迭代期间从底层集合中删除元素,并具有明确定义的语义。
2、方法名称得到改进。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<String>();//创建集合对象
//添加元素
collection.add("hello");
collection.add("meet");
collection.add("Iterator");
//创建迭代器
Iterator<String> it = collection.iterator();
//next:返回迭代器中的下一个元素
/*
System.out.println(it.next());//hello
System.out.println(it.next());//meet
System.out.println(it.next());//Iterator
System.out.println(it.next());//抛出异常:java.util.NoSuchElementException:表示被请求元素不存在
*/
//hasNext:如果迭代器有更多元素,则返回true
/*
if(it.hasNext()){
System.out.println(it.next());//结果为hello
}
if(it.hasNext()){
System.out.println(it.next());//结果为meet
}
if(it.hasNext()){
System.out.println(it.next());//结果为Iterator
}
if(it.hasNext()){
System.out.println(it.next());//这次没有抛出异常
//对于第四个没有元素时,这里if里面的it.hasNext()判断集合中有没有元素,如果有,则结果为true时
//才会执行输出语句;反之没有,则不执行输出语句,所以这里不会抛出异常
} */
//用for循环语句改进
// for (int i = 0; i < collection.size(); i++) {
// if (it.hasNext()){
// System.out.println(it.next());
// }
// }
//用while循环改进
while(it.hasNext()){
// System.out.println(it.next());
//推荐下面方式去输出
String s = it.next();
System.out.println(s);
}
}
}
- Collection的一个具体案例
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
//案例:Collection集合存储学生对象并遍历
public class collectiontest03 {
public static void main(String[] args){
//1、创建学生类------------->Student
//2、创建Collection集合
Collection<Student> c = new ArrayList<Student>();
//3、创建学生对象
Student s1 = new Student(16,"小王");
Student s2 = new Student(18,"小明");
Student s3 = new Student(10,"小芳");
//把学生添加到集合中去
c.add(s1);
c.add(s2);
c.add(s3);
//5、遍历集合,使用迭代器的方式
Iterator<Student> it = c.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getAge()+","+s.getName());
}
}
}
三、List(有序可重复)
3.1、List的概述
java.util
Interface List<E>
public interface List<E>
extends Collection<E>
-
有序集合(也称为序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。
-
与Set集合不同,列表通常允许重复的元素
-
List集合的特点:
- 有序:存储和取出元素的顺序是一致的
- 可重复:存取的元素是可以重复的
-
List集合子类ArrayList、LinkedList特点
- ArrayList:底层数据结构是数组,查询快,增删慢;
- LinkedList:底层数据结构式链表,查询慢,增删快;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Listdemo01 {
public static void main(String[] args) {
//List特点展示
//1、创建List集合对象
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("hello");
list.add("meet");
list.add("List");
list.add("List");
/*正好可以看出两个特点:
1、有序,即存取顺序都是一致的
2、可重复,即储存的元素可以重复
*/
System.out.println(list);//结果为[hello, hello, meet, List, List]
//遍历集合
//因为List继承Collection,所以Collection用迭代器遍历的方式,List也可以用
//方式一
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
//遍历集合,方式二
// for (int i = 0; i < list.size(); i++) {
// String s = list.get(i);
// System.out.println(s);
// }
}
}
- List特有方法
import java.util.ArrayList;
import java.util.List;
//collection没有,而List特有的方法,其子类也有该方法
public class Listdemo02 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("add");
list.add("remove");
list.add("set");
list.add("get");
System.out.println(list);//结果为[add, remove, set, get]
//void add(int index, E element):将指定的元素插入此列表中的指定位置(可选操作)。
// list.add(3,"insertcode");//在三号位置插入insertcode
// list.add(5,"addway");//五号位置插入addway
// System.out.println(list);//结果为[add, remove, set, insertcode, get, addway]
/*注意:如果只写list.add(5,"addway");//五号位置插入addway这一句的话;
* 会抛出越界异常java.lang.IndexOutOfBoundsException: Index: 5, Size: 4;
* 可以分析出,原来只有四个元素,现在直接超过了这个集合元素空间大小了,所以抛出异常
* */
//E remove(int index):删除该列表中指定位置的元素,并返回被删除元素。
// System.out.println(list.remove(3));//结果为get
// System.out.println(list.remove(5));//java.lang.IndexOutOfBoundsException,越界异常
//E set(int index, E element):用指定的元素替换此列表中指定位置的元素,并返回被修改的值
// System.out.println(list.set(2,"setway"));//结果为set
// 这个也要注意越界这个异常
//E get(int index):返回此列表中指定位置的元素
// System.out.println(list.get(3));//结果为get
// 这个也要注意越界这个异常
}
}
- 注:对于有指定索引值的,都需要注意java.lang.IndexOutOfBoundsException,越界异常
import gather.Collection.Student;
import java.util.ArrayList;
import java.util.List;
//案例:List集合存储学生对象并遍历
public class Listdemo03 {
public static void main(String[] args){
//1、创建学生类------------->Student
//创建集合
List<Student> list = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student(15,"王");
Student s2 = new Student(14,"赵");
Student s3 = new Student(17,"李");
//添加到集合中
list.add(s1);
list.add(s2);
list.add(s3);
//遍历集合
//方式一
// Iterator<Student> it = list.iterator();
// while(it.hasNext()){
// Student s = it.next();
// System.out.println(s.getAge()+","+s.getName());
// }
//方式二
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getAge()+","+s.getName());
}
}
}
3.2、List的并发修改异常
- ConcurrentModificationException:并发修改异常
- 产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际值不一致
- 解决方式:用for循环遍历,然后做集合遍历
import java.util.ArrayList;
import java.util.List;
public class Listdemo04 {
public static void main(String[] args) {
List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.add("javase");
//遍历集合,得到每个元素,看是否有world;如果有,则添加一个“javee”
// Iterator<String> it = l.iterator();
// while(it.hasNext()){
// String s = it.next();//问题出在next上,为什么?
// //当迭代器在遍历过程中时,我们执行了下面的操作,导致了next源码中判断过程
// // 修改的次数和预期的修改次数不相等了,就导致出现了异常。
// if(s.equals("world")){
// l.add("javaee");
// }
// System.out.println(s);
// /*此时会抛出java.util.ConcurrentModificationException:并发修改异常
// *当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
// * */
// }
//对于上面的情况我们可以采用集合遍历的第二种方式,for循环遍历
for (int i = 0; i < l.size(); i++) {
// if(l.get(i)=="e"){
// l.add("javaee");
// }
//推荐第二种
String s = l.get(i);
if (s.equals("world")){
l.add("javaee");
}
System.out.println(l.get(i));
}
}
}
3.3、ListIterator(列表迭代器)
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置。
public interface ListIterator<E> extends Iterator<E>
ListIterator<E> listIterator() 返回列表中的列表迭代器(按适当的顺序)。
ListIterator<E> listIterator(int index) 从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
当中的方法
void add(E e) 将指定的元素插入列表(可选操作)。
boolean hasNext() 返回 true如果遍历正向列表,列表迭代器有多个元素。
boolean hasPrevious() 返回 true如果遍历反向列表,列表迭代器有多个元素。
E next() 返回列表中的下一个元素,并且前进光标位置。
int nextIndex() 返回随后调用 next()返回的元素的索引。
E previous() 返回列表中的上一个元素,并向后移动光标位置。
int previousIndex() 返回由后续调用 previous()返回的元素的索引。
void remove() 从列表中删除由 next()或 previous()返回的最后一个元素(可选操作)。
void set(E e) 用指定的元素替换由 next()或 previous()返回的最后一个元素(可选操作)。
//方法案例
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Listdemo05 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("add");
list.add("next");
list.add("hasNext");
list.add("previous");
list.add("hasPrevious");
// System.out.println(list);
ListIterator<String> lit = list.listIterator();
//add:将指定元素插入集合中
// lit.add("java");
// System.out.println(list);//结果为[java, add, next, hasNext, previous, hasPrevious]
//next:返回迭代中下一个元素
// System.out.println(lit.next());//结果为add
// System.out.println(lit.next());//结果为next
//hasNext:如果迭代中有很多元素,则返回true
// System.out.println(lit.hasNext());//true
//正序遍历集合
while(lit.hasNext()){
String s = lit.next();
System.out.println(s);
}
System.out.println("==================");
//反序遍历
while(lit.hasPrevious()){
String s = lit.previous();
System.out.println(s);
}
/*如果只写反序遍历是不会输出任何值的,且如果先写后序再写前序,后序也是不能输出任何值的;
*但是我当我先写了正序遍历后再写了反序遍历就能都运行出来;
*知道这是为什么吗?
* 这是因为迭代器的指针默认是向左的,直接使用反序遍历时不会输出值的,所以反序遍历集合前应该先正序遍历
* 使其迭代器指针指示向右
* */
}
}
Iterator<String> it = l.iterator();
while(it.hasNext()){
String s = it.next();//问题出在next上,为什么?
//当迭代器在遍历过程中时,我们执行了下面的操作,导致了next源码中判断过程
// 修改的次数和预期的修改次数不相等了,就导致出现了异常。
if(s.equals("world")){
l.add("javaee");
}
System.out.println(s);
/*此时会抛出java.util.ConcurrentModificationException:并发修改异常
*当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
* */
}
//如果用List做下面的遍历操作会抛出并发修改异常
//但是用ListIterator则可以进行这样的操作
ListIterator<String> lit = list.listIterator();
while(lit.hasNext()){
String s = lit.next();
if(s.equals("add")){
lit.add("javaee");
}
}System.out.println(list);
//可以去都运行一下,比较两个的区别
3.4、增强for循环
增强for循环:简化数组和Collection集合的遍历
- 实现Iterable接口的类允许其对象称为增强型for语句的目标
- 它是JDK1.5之后出现的,其内部原理是一个Iterator迭代器
增强for的循环格式:
for(元素数据类型变量名 : 数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
例如:
int[] arr ={1,2,3,4};
for(int i:arr){
System.out.println(i);
}
import java.util.ArrayList;
import java.util.List;
public class Fordemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i:arr) {
System.out.println(i);
}
System.out.println("=============");
String[] str = {"hello","meet","for"};
for (String s:str) {
System.out.println(s);
}
System.out.println("=============");
List<String> list = new ArrayList<String>();
list.add("good");
list.add("great");
for(String li:list){
System.out.println(li);
}
/*
System.out.println("=============");
//内部是一个Iterator迭代器
for(String s:list){
if (s.equals("good")){
list.add("javase");
}
}
System.out.println(list);//ConcurrentModificationException抛出并发异常
//依此说明其内部相当于Iterator迭代器
*/
}
}
3.5、ArrayList
java.util.ArrayList<E>//E为此列表元素的类型
//在出现<E>的地方可以使用引用数据类型替换即可,如ArrayList<String> ; ArrayList<Animal>
ArrayList
- 可调整大小的数组实现
:是一种特殊的数据类型,泛型。
ArrayList构造方法和添加方法
方法名 | 说明
public ArrayList() | 创建一个空的集合对象
public boolean add(E e) | 将指定的元素追加到此集合的末尾
public void add(int index,E element) | 在此集合中的指定位置插入指定的元素
常用的有:add、remove、contains、size等
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
// ArrayList<String> arrayList = new ArrayList<>(); jdk1.7后的新特性,后面<>可以自动识别数据类型
ArrayList<String> arrayList = new ArrayList<String>();//创建空的集合对象
//向集合中添加元素
// System.out.println(arrayList.add("Hello,ArrayList"));//这一句相当于判断,结果肯定为true;所以我们可以直接写
// arrayList.add("Hello,ArrayList");//结果为[Hello,ArrayList]
arrayList.add("Hello");
arrayList.add("ArrayList");//结果为[Hello, ArrayList]
//以上这两种方式输出结果他们是有区别的注意观察哦,第二种方式逗号后面是有空格的
//public void add(E e) | 在此集合中的指定位置插入指定的元素
arrayList.add(1,"firstmeeting");//结果为[Hello, firstmeeting, ArrayList]
//arrayList.add(3,"firstmetting");
/*注意我们可以看到数组里面只有两个元素而我们写的从第三个元素索引,所以会报错
* java.lang.IndexOutOfBoundsException: Index: 3, Size: 2
* 可以很清楚的知道错误为----------->数集合的索引越界
* */
//输出ArrayList对象; 当结果为[],此时是没有元素的,若有元素则在[]里面。
System.out.println(arrayList);
}
}
- 以下示例是常见方法的使用,更多方法可以依据API文档使用测试
import java.util.ArrayList;
public class ArrayListtest02 {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
array.add("Hello");
array.add("collection");
array.add("class");
System.out.println(array);//结果为[Hello, collection, class]
//remove的两种方式
// System.out.println(array.remove("Hello"));//删除指定元素,返回删除是否成功;这里的结果为true;
// System.out.println(array.remove(0));//删除指定索引处的元素,返回被删除的元素 ;这里结果为Hello;
//contains:判断此列表是否包含指定的元素,如果有则返回 true ,反之为false
// System.out.println(array.contains("class"));//结果为true
// System.out.println(array.contains("aaaa"));//结果为false
//size:返回此列表中的元素数。
// System.out.println(array.size());//结果为3
//set:用指定的元素 "替换" 此列表中指定位置的元素。
// array.set(2,"first");
// System.out.println(array);//结果为[Hello, collection, first],说明把原来的class成功替换掉
//get:返回此列表中指定位置的元素;
// System.out.println(array.get(1));//结果为collection
}
}
- 注:这里面的方法中只要有索引条件的,都要注意java.lang.IndexOutOfBoundsException,即越界情况哦!
import java.util.ArrayList;
//案例1:存储字符串并遍历
public class ArrayListtest03 {
public static void main(String[] args) {
//1、创建对象
ArrayList<String> array = new ArrayList<String>();
//2、在集合中添加字符串对象
array.add("Hello");
array.add("javaSE");
array.add("Collection");
array.add("class");
array.add("Devin");
//3、遍历集合,首先要能获取到集合中的每个元素
//4、其次要能够获取其集合长度
//实现方法一
// System.out.println(array.get(0));
// System.out.println(array.get(1));
// System.out.println(array.get(2));
// System.out.println(array.get(3));
// System.out.println(array.get(4));
//实现方法二
for (int i = 0; i <array.size() ; i++) {
// System.out.println(array.get(i));//方式一输出
//推荐方法二,可以便于其他更多的操作
String s = array.get(i);
System.out.println(s);
}
}
}
import java.util.ArrayList;
//案例2:存储学生对象,并遍历
public class ArrayListtest04 {
public static void main(String[] args) {
//1、创建学生类----->Student
//这里自己创建即可;
//2、创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
//3、创建学生对象
Student s1 = new Student(12,"李明");
Student s2 = new Student(18,"王芳");
Student s3 = new Student(16,"王华");
//4、添加学生对象到集合中
array.add(s1);
array.add(s2);
array.add(s3);
//5、遍历集合
for (int i = 0; i <array.size() ; i++) {
Student s = array.get(i);
System.out.println(s.getAge()+","+s.getName());
}
}
}
3.6、LinkedList
java.util.LinkedList<E>
- 其基本用法和ArrayList差不多,可以仿照学习
import java.util.LinkedList;
public class LinkedListdemo01 {
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("hello");
ll.add("meet");
ll.add("you");
//遍历方法一共有三种
//方法一
// for (int i = 0; i < ll.size(); i++) {
// String s = ll.get(i);
// System.out.println(s);
// }
//方法二
// Iterator<String> it = ll.iterator();
// while(it.hasNext()){
// String s = it.next();
// System.out.println(s);
// }
//方法三
for(String s:ll){
System.out.println(s);
}
}
}
- LinkList特有方法
import java.util.LinkedList;
public class LinkedListdemo02 {
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("hello");
ll.add("meet");
ll.add("you");
System.out.println(ll);//[hello, meet, you]
//这里只测了部分方法,其他方法基本一样
// ll.addFirst("first");//addFisrt
// System.out.println(ll);//[first, hello, meet, you]
// System.out.println(ll.getLast());//you
// System.out.println(ll.removeFirst());//hello
}
}