ArrayList集合

前言:种一棵树最好是在十年前,其次是现在。。普遍来说,在学校跑得快的人,往往在社会上也跑得快

List集合

概述

集合:装元素 (集合里面可以装不同的数据类型 集合里面可以存放无数个元素) 数组:装元素 (数组里面只能装相同类型的元素 数组里面装元素有个数限制) JCF(Java Collections Framwork) java集合框架 1.Collections [单值类型集合] <1>List [有序][不唯一] a.ArrayList b.Vector c.LinkedList d.Stack <2>Set [无序][唯一] a.SortedSet 2.Map [键值对类型集合] <1>SortedMap 面试题: List Set Map是不是属于同一个等级? 答:List Set属于Collection的子接口,Map和Collection属于同一个等级

ArrayList:*

特点:有序(指的是添加顺序有序) 不唯一 ArrayList底层是基于数组实现的 ->将要存放的数据放在Object[]中 可以这样理解: 数组是一个蛋托,存储空间连续、大小相等,集合可以看成一个大卡车,大卡车里面可以装各种类型的物品(对象) 由于ArrayList底层基于Object[]实现的 所以所有的引用数据类型都可以存放在集合里面 但是基本数据类型不能放在集合里面, 那基本数据类型怎么装呢? 就好像大卡车不能直接装水,但是把水放在瓶子里再放在卡车里就行,这里的瓶子就相当于包装类 ArrayList0:包装类 boolean -> Boolean; char -> Charactor; byte -> Byte; short -> Short; int -> Integer; long -> Long; float -> Float; double -> Double 1.基本数据类型->包装类 int x = 45; //jdk5.0之前 Integer y = Integer.valueOf(x); //jdk5.0开始 Integer y = x; //自动打包 2.包装类->基本数据类型 Integer x = new Integer(55); //jdk5.0之前 int y = x.intValue(); //jdk5.0开始 int y = x;//自动打包 *:Integer类会自动缓存-128到127之间所有的数字,常量池查找机制,跟用不new方式,创建String对象类似 ---------- public class Test01 { public static void main(String[] args){ Integer x = 10; Integer y = 10; System.out.println(x == y);//打印 true //------// Integer a = 100; Integer b = 100; System.out.println(a ==b);//打印 true //------// Integer m = 1000; Integer n = 1000; System.out.println(m == n);//打印 false } } ---------- 包装类里面提供了一个方法(parseXXXX) 可以将String类型转换成对应的基本数据类型 String x = "true"; boolean y = Boolean.parseBoolean(x);//true String str = "234"; int x = Integer.parseInt(str); System.out.prinltn(x + 3);//打印237 ArrayList1:基本用法和特点 1.如何创建一个ArrayList集合对象 //jdk5.0之前 默认往集合里面添加都是Object对象 ArrayList list = new ArrayList(); //jdk5.0开始 可以加泛型(表示集合里面只能装某一种数据类型) ArrayList<泛型> list = new ArrayList<泛型>(); //jdk7.0开始 ArrayList<泛型> list = new ArrayList<>(); 2.如何往集合里面添加元素 A:一次只能添加一个元素: 集合对象.add(元素); B:一次添加多个元素的方式: Collections.addAll(集合对象,元素1,元素2,元素3......); 或者 集合对象.addAll(另一个集合对象); 3.如何得到集合的大小 集合对象.size() 4.如何得到集合里面的某一个对象 集合对象.get(下标) 5.如何判断一个集合里面是否包含某一个元素 集合对象.contains(元素); 6.如何遍历集合对象 A:for + x(下标) for(int x = 0 ; x < list.size() ; x++){ System.out.println(list.get(x)); } B:foreach forin since jdk5.0 for(泛型 x : 集合对象){ System.out.println(x); } C:Iterator 迭代器 for(得到迭代器对象;判断迭代器是否还有下一个元素;){ 取出迭代器里面下一个元素 -> x; } for(Iterator<泛型> car = list.iterator();car.hasNex();){ 泛型 x = car.next();//x -> 元素 --------- public class Test02 { public static void main(String[] args){ ArrayList<String> list = new ArrayList<>(); list.add("Anny"); list.add("Jack"); Collections.addAll(list,"Anron","Lee"); //打印出来所有以A开头的名字 for(Iterator<String> car = list.iterator();car.hasNext();){ String str = car.next(); if(str.startsWith("A")){ System.out.println(str); } } } } --------- ArrayList2: ArrayList里面提供一个方法 可以删除指定下标的元素 list.remove(x); 清空集合:list.clear(); ArrayList3: ArrayList里面提供一个方法 可以直接的删除某一个元素 list.remove(Object obj); *:一个remove(Object obj)只能删除一个元素 --------- public class Test03 { public static void main(String[] args){ ArrayList<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); list.add("B"); list.remove("B"); System.out.println(list);//打印 [A, C, B] } } -------- public class Test04 { public static void main(String[] args){ ArrayList<Integer> list = new ArrayList<>(); list.add(666); list.add(777); list.add(888); list.add(777); list.remove(new Integer(666));//注意这里不能直接写666 会当成下标 报越界异常 System.out.println(list);//打印 [777, 888, 777] } } -------- ArrayList4: list.remove(Object obj)方法,底层需要尊重equals()的比较规则; 参数obj表示一个参照物,不是表示集合里面一定需要obj这个对象,底层拿着obj 这个参照物和集合里面的每一个元素做equals比较,如果集合里面有一个元素和这个参照物视为 相等对象,那么将集合对应的这个元素删除,所以这里需要覆写equals()方法 制定比较规则 -------- public class Test05 { public static void main(String[] args){ ArrayList<Student> list = new ArrayList<>(); Student stu1 = new Student("Tomcmd"); Student stu2 = new Student("汪亮"); Student stu3 = new Student("Tomcmd"); list.add(stu1); list.add(stu2); System.out.println(list.size());//打印 2 list.remove(stu3);//如果stu3.equals(stu1)就把stu1删除,如果不覆写,就比较对象 System.out.println(list.size());//打印 1 } } class Student{ String name; public Student(String name){ this.name = name; } @Override public boolean equals(Object obj){ if(obj == null)return false; if(!(obj instanceof Student))return false; if(obj == this)return true; return this.name.equals(((Student)obj).name); //注意:假如直接返回true 表示内存里面完全不同的两个对象 也被当成相等的对象 //即使是内存里面同一个对象 也被视为不同的两个对象 } } ---------- ArrayList5: 谁主张,谁举证 要被删除的元素会主动的调用他自己类的equals方法和集合里面的每一个元素做比较 ---------- public class Test06 { public static void main(String[] args){ ArrayList list = new ArrayList(); Student1 stu = new Student1("Tomcmd"); Teacher tea = new Teacher("Wangliang"); list.add(stu); System.out.println(list.size());//打印 1 list.remove(tea);//调用tea.equals()方法和list中的每一个元素比较 这里无论怎么比都返回false 删除失败 System.out.println(list.size());//打印 1 } } class Student1{ String name; public Student1(String name){ this.name = name; } @Override public boolean equals(Object obj){ return true;//内存里面Student1的对象跟任意对象相等 } } class Teacher{ String name; public Teacher(String name){ this.name = name; } @Override public boolean equals(Object obj){ return false;//内存里面Teacher对象跟任意对象不等 即使是同一个对象 } } --------- ArrayList6: 当我们使用迭代器遍历集合的过程中,不允许对集合的整体进行添加/删除操作,否则 都会触发CME(并发修改异常) ConcurrentModificationException 如果需求一定要求一边遍历,一边删除,只能使用迭代器的remove()方法 car.remove();无参 *:foreach底层基于迭代器实现的 --------- public class Test07 { public static void main(String[] args){ ArrayList<Integer> list = new ArrayList<>(); list.add(55); list.add(54); list.add(67); Collections.addAll(list,76,98,32); //删除集合里面所有不及格的学生的成绩 for(Iterator<Integer> car = list.iterator();car.hasNext();){ Integer score = car.next(); if(score < 60){ car.remove(); } } System.out.println(list);//打印 [67,76,98] } } -------- 这个题很关键 public class Test08 { public static void main(String[] args){ //x:专门用来统计对集合操作次数 操作一次将x值加一(添加/删除) //x = 0 ArrayList<Integer> list = new ArrayList<>(); //x = 6 Collections.addAll(list,29,55,43,17,67); //y = x;当利用Iterator遍历时,首先会将x的值复制给Iterator中的y,当Iterator操作一次时,x和y同时加一 //而list操作时,只加x 不加y //car.hasNext()会将光标往下移再移回来 car.next()直接将光标下移一个单位 for(Iterator<Integer> car = list.iterator();car.hasNext();){ //每次取值时,先判断x是否等于y,如果相等 car.next()才返回值,如果x不等于y 报错ConcurrentModificationException Integer x = car.next(); if(x < 60) //list.remove(x); car.remove(); } System.out.println(list);//打印[67] } } -------- ArrayList7: 当我们创建一个数组对象时,必须明确数组空间大小,ArrayList底层基于Object[]实现的, 程序员其实可以按照自己的意愿决定底层数组对象开辟多大空间 ArrayList构造方法可以传参数,参数表示底层数组空间大小,我们之前一直没在构造方法里面 传过参数 -> 无参构造方法 默认开辟10块空间,不代表只能装10个元素;集合可以装无数个元素,底层自动扩容 扩容: jdk6.0及之前 jdk7.0及之后 x*3/2+1 x+(x>>1) 10->16->25... 10->15->22.... 注意:在开发过程中,尽量避免扩容: 1.创建一个新的数组对象 2.将老数组里面的元素复制到新的数组对象里面 3.改变引用指向 4.回收老数组对象,gc自动回收 其中,ArrayList提供直接将集合大小扩容到指定大小的方法 list.ensureCapacity(int x) ->更加高效 还提供直接将集合的大小缩小为元素个数的方法 list.trimToSize() ArrayList8: 模拟实现ArrayList底层的基本方法 -------- public class Test09 { public static void main(String[] args){ CustomArrayList<String> list = new CustomArrayList<>(); list.add("哈士奇"); list.add("博美"); list.add("吉娃娃"); System.out.println(list);//[哈士奇,博美,吉娃娃] list.remove(0); System.out.println(list);//[博美,吉娃娃] } } class CustomArrayList<E>{ //属性 private Object[] data; private int size; //构造方法 public CustomArrayList(int capacity){ data = new Object[capacity]; } public CustomArrayList(){ this(10);//默认开辟10块空间 } //成员方法 /** * 得到ArrayList元素个数 */ public int size(){ return size; } /** * 得到ArrayList某一个元素 * @param index 表示要得到元素的下标 * @return */ public Object get(int index){ if(index < 0) { System.out.println("参数错误"); return null; } return data[index]; } /** * 添加一个对象的方法 * @param obj 表示要加入的元素 */ public void add(E obj){ //注意,这里是加泛型 /* 首先判断数组空间是否已满,如果已满 1.重新创建数组,开辟空间,并进行扩容 jdk6.0及之前x*3/2+1 jdk7.0及之后 x+(x>>1) x指 2.将原数组元素复制到新数组中(System.arraycopy()方法实现) 3.将原数组引用指向新数组 4.回收老数组对象(由gc来做) 5.将obj添加到新数组中 6.size++ 如果未满 1.将obj添加到新数组中 2.size++ 可以看到两种情况有公共步骤,所以可以提出来 */ if(data.length == size){ Object[] temp = new Object[size*3/2+1]; System.arraycopy(data,0,temp,0,size); data = temp; } data[size++] = obj; } /** *删除指定下标元素的方法 * @param index 需要删除的指定元素的下标 */ public void remove(int index){ System.arraycopy(data,index+1,data,index,size-index-1); size--;//这里一定要加size-- } /** * 删除指定对象的元素 * @param obj 要删除的对象 */ public void remove(Object obj){ for(int x = 0 ; x < size ; x++){ if(obj.equals(data[x])){ remove(x);//只删除一次 break; } } } /** * 覆写toString()方法,拼接打印对象显示的内容 * @return */ @Override public String toString(){ StringBuffer buffer = new StringBuffer("["); for(int x = 0 ; x < size ; x++){ buffer.append(x == size-1?(data[x] + "]"):data[x] + ","); } return buffer.toString(); } } ------- ArrayList9: 内存图:
面试题: ArrayList和Vector之间的区别?***** 1.线程同步问题: Vector同一时间允许一个线程进行访问 效率较低,但是不会出现并发错误; ArrayList同一时间允许多个线程进行访问,效率较高,但可能会出现并发错误; 但是从jdk5.0开始,Collections里面提供了一个方法(SynchronizedList) 可以将一个线程不安全的ArrayList变成一个线程安全的集合对象,于是Vector渐渐被淘汰 2.扩容机制不同: ArrayList:分版本 jdk6.0及之前 x*3/2+1 jdk7.0及之后 x+(x>>1) Vector:分构造方法 Vector(10) ->2倍扩容 10->20->40.... Vector(10,3) -> 定长扩容 10->13->16->19.... 3.出现的版本不同 Vector:since jdk1.0 ArrayList:since jdk1.2 LinkedList和ArrayList之间的区别? LinkedList底层的数据结构是链表 ArrayList底层的数据结构是数组 由于他们底层的数据结构不同,所以导致他们的优劣势不同 ArrayList:底层基于数组实现的 优势:随机访问 遍历查找 劣势:添加/删除一个元素 -> get() LinkedList:底层基于链表实现的 优势:添加/删除元素 劣势:随机访问 遍历查找 当我们在用LinkedList的时候,尽量避免使用get(int 下标) -> 效率非常低 Stack:用数组模拟栈结构 -------- public class Test10{ public static void main(String[] args){ Stack<Integer> ss = new Stack<Integer>(); ss.push(888); ss.push(999); ss.push(666);//往栈顶压入一个元素 System.out.println(ss.pop());//从栈顶弹出一个元素 System.out.println(ss.pop()); System.out.println(ss.pop());//666 999 888 //ArrayList LinkedList } } --------
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值