数组存放地址值的内存图
数组和集合的区别
- 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值。
- 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象。
数组长度是固定的,不能自动增长。
集合的长度的是可变的,可以根据元素的增加而增长。
数组和集合什么时候用?
如果元素个数是固定的推荐用数组
如果元素个数不是固定的推荐用集合
集合体系图
Collection基本功能
boolean add(E e)
- 如果是List集合,一直都返回true,因为List集合可以存储重复元素
- 如果是Set集合,当存储重复元素的时候,会返回false
- ArrayList的父类的父类重写了toString方法,所以在打印对象的引用的时候,输出的结果不是Object类中toString的结果。
boolean remove(Object o) 删除指定元素
void clear() 清空集合
boolean contains(Object o) 判断是否包含
boolean isEmpty() 判断集合是否为空
int size() 获取集合中元素的个数
集合的遍历
Collection c = new ArrayList(); c.add(new Student("张珊",22)); c.add(new Student("盼盼",23)); c.add(new Student("安琪",24)); c.add(new Student("王琪",25)); c.add(new Student("杨振",26)); c.remove(new Student("安琪",24)); Object[] arr = c.toArray(); Student s = null; for (int i = 0; i < arr.length; i++) { //System.out.println(arr[i]); s = (Student)arr[i]; System.out.println(s.getName()+"..."+s.getAge()); }
Collection集合的带All功能测试
- boolean addAll(Collection c)
c1.addAll(c2); 将c2中的每一个元素添加到c1中
c1.add(c2); 将c2当作一个集合添加到c1中,成为c1中的一个元素
- boolean removeAll(Collection c)
c1.removeAll(c2); 从c1中移除c2所包含的元素
- boolean containsAll(Collection c)
c1.containsAll(c2); 判断调用的集合是否包含传入的集合
- boolean retainAll(Collection c)
c1.retainAll(c2); 取交集(c1变成c1与c2的交集),如果调用的集合改变就返回true,不变就返回false。
集合遍历之迭代器(Iterator)
集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
public static void demo2() { Collection c = new ArrayList(); c.add(new Student("张珊",22)); c.add(new Student("盼盼",23)); c.add(new Student("安琪",24)); c.add(new Student("王琪",25)); c.add(new Student("杨振",26)); Object[] arr = c.toArray(); Student s = null; //获取迭代器 Iterator it = c.iterator(); while(it.hasNext()) { //System.out.println(it.next()); s = (Student)it.next(); System.out.println(s.getName()+"..."+s.getAge()); } }
迭代器原理
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可
迭代器源码解析
- 在eclipse中ctrl + shift + t找到ArrayList类
- ctrl+o查找iterator()方法
- 查看返回值类型是new Itr(),说明Itr这个类实现Iterator接口
- 查找Itr这个内部类,发现重写了Iterator中的所有抽象方法
List集合的特有功能
void add(int index,E element)
在指定位置插入指定元素
index<=size并且index>=0都不会报越界异常
E remove(int index)
通过索引删除元素
将被删除的元素返回
删除的时候不会自动装箱,把111当作索引
E get(int index)
通过索引遍历List集合
public static void demo1() { List list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); // Object o = list.get(0); // System.out.println(o); // System.out.println(list); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } }
List集合存储学生对象并遍历
List list = new ArrayList(); list.add(new Student("张三", 18)); list.add(new Student("李四", 18)); list.add(new Student("王五", 18)); list.add(new Student("赵六", 18)); for(int i = 0; i < list.size(); i++) { Student s = (Student)list.get(i); System.out.println(s.getName() + "," + s.getAge()); }
E set(int index,E element)
将指定位置的元素修改
public static void demo2() { List list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.set(2, "张珊"); System.out.println(list); }
并发修改异常产生的原因及解决方案————ListIterator
ConcurrentModificationException出现
* 迭代器遍历,集合修改集合
解决方案
* a:迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add())
* b:集合遍历元素,集合修改元素
public static void main(String[] args) { List list = new ArrayList(); list.add("a"); //Object obj = new String(); list.add("b"); list.add("world"); list.add("d"); /*Iterator it = list.iterator(); //获取迭代器 while(it.hasNext()) { //判断是否有元素 String str = (String) it.next(); //向下转型 if("world".equals(str)) { list.add("javaee"); //遍历的同时添加元素,并发修改,会报异常java.util.ConcurrentModificationException } } System.out.println(list);*/ ListIterator lit = list.listIterator(); while(lit.hasNext()) { //判断是否有元素 String str = (String) lit.next(); //向下转型 if("world".equals(str)) { //list.add("javaee"); //遍历的同时添加元素,并发修改,会报异常java.util.ConcurrentModificationException lit.add("javaee"); } } System.out.println(list); }
Vector的迭代
Vector v = new Vector(); //创建集合对象,List的子类 v.addElement("a"); v.addElement("b"); v.addElement("c"); v.addElement("d"); //Vector迭代 Enumeration en = v.elements(); //获取枚举 while(en.hasMoreElements()) { //判断集合中是否有元素 System.out.println(en.nextElement());//获取集合中的元素 }
数据结构之数组和链表
* A:数组
* 查询快修改也快
* 增删慢
* B:链表
* 查询慢,修改也慢
* 增删快
数组
链表
List的三个子类的特点
A:List的三个子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
补充:
Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
B:List有三个儿子,我们到底使用谁呢?
查询修改多用ArrayList
增删多用LinkedList
如果都多ArrayList
去除ArrayList中重复自定义对象元素
重写toString()方法和equals()方法
contains()方法判断是否包含,底层依赖的是equals()方法
remove()方法判断是否删除,底层依赖的是equals()方法
public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(new Person("张珊",23)); list.add(new Person("张珊",23)); list.add(new Person("王琪",24)); list.add(new Person("王琪",24)); list.add(new Person("王琪",24)); ArrayList newList = getSingle(list); System.out.println(newList); list.remove(new Person("王琪",24)); System.out.println(list); } public static ArrayList getSingle(ArrayList list) { ArrayList newList = new ArrayList(); Iterator it = list.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newList.contains(obj)) { newList.add(obj); } } return newList; }
方法重写
@Override public String toString() { return "Person [name="+name+", age="+age+"]"; } @Override public boolean equals(Object obj) { Person p = (Person)obj; return this.name.equals(p.name)&&this.age==p.age; }
LinkedList类特有功能
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
public E get(int index);
栈和队列数据结构
* 栈
* 先进后出
* 队列
* 先进先出
eg:模拟栈结构
import java.util.LinkedList; public class Stack { private LinkedList list = new LinkedList(); public void in(Object obj) { list.addLast(obj); } public Object out() { return list.removeLast();//队列只需将Last改成Fast } public boolean isEmpty() { return list.isEmpty(); } }
public class Demo3_LinkedList { public static void main(String[] args) { Stack s = new Stack(); s.in("a"); s.in("b"); s.in("c"); s.in("d"); s.in("e"); while(!s.isEmpty()) { System.out.println(s.out()); } } }
泛型概述和基本使用
A:泛型概述
B:泛型好处
提高安全性(将运行期的错误转换到编译期)
省去强转的麻烦
C:泛型基本使用
<>中放的必须是引用数据类型
D:泛型使用注意事项
前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
泛型最好不要定义成Object类,没有意义
public class Demo4_Generic { public static void main(String[] args) { ArrayList<Person> list = new ArrayList<Person>(); list.add(new Person("张珊",23)); list.add(new Person("杨振",24)); Iterator<Person> it = list.iterator(); while(it.hasNext()) { Person p = it.next(); System.out.println(p.getName()+"..."+p.getAge()); } } }
泛型方法的概述和使用
A:泛型方法概述
把泛型定义在方法上
B:定义格式
public <泛型类型> 返回类型 方法名(泛型类型 变量名)
注意:方法泛型最好与类泛型一致,如果不一致,需要在方法上声明该泛型
静态方法必须声明自己的泛型,不能和类一致,因为静态方法是随着类的加载而加载的,当类加载进来还没有创建对象
泛型接口
A:泛型接口概述
把泛型定义在接口上
B:定义格式
public interface 接口名<泛型类型>
C:案例演示
泛型接口的使用
public class Demo5_Generic { public static void main(String[] args) { Demo d = new Demo(); d.show("hello"); } } interface Inter<T>{ public void show(T t); } class Demo implements Inter<String> { public void show(String s) { System.out.println(s); } }
泛型高级之通配符
* A:泛型通配符<?>
* 任意类型,如果没有明确,那么就是Object以及任意的Java类了
* B:? extends E
* 向下限定,E及其子类
* C:? super E
* 向上限定,E及其父类
当右边的泛型是不确定时,左边可以指定为?。
public class Teacher extends Person { public Teacher() { } public Teacher(String name, int age) { super(name, age); } }
public static void main(String[] args) { ArrayList<Person> list1 = new ArrayList<>(); list1.add(new Person("张珊",23)); list1.add(new Person("安琪",24)); list1.add(new Person("盼盼",25)); //System.out.println(list1); ArrayList<Teacher> list2 = new ArrayList<>(); list2.add(new Teacher("哈哈",20)); list2.add(new Teacher("呵呵",30)); //System.out.println(list2); list1.addAll(list2); //list2.addAll(list1); System.out.println(list1); }
增强for的概述和使用
* A:增强for概述
* 简化数组和Collection集合的遍历
* B:格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
* C:案例演示
* 数组,集合存储元素用增强for遍历
* D:好处
* 简化遍历
public static void main(String[] args) { int[] arr = {2,3,4,5}; for (int i : arr) { } for(int i:arr) { System.out.print(i+" "); } System.out.println("--------------------"); ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); for (String string : list) { System.out.print(string+" "); } }
三种迭代的能否删除
- 普通for循环,可以删除,但是索引要减减
- 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
- 增强for循环不能删除,只能遍历
import java.util.ArrayList; import java.util.Iterator; public class Demo8 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("b"); list.add("c"); list.add("b"); //1,普通for循环删除 for (int i = 0; i < list.size(); i++) { if("b".equals(list.get(i))) { list.remove(i--); } } //2,迭代器删除 Iterator it = list.iterator(); while(it.hasNext()) { if("b".equals(it.next())) { it.remove(); } } //3,增强for循环不能删除,ConcurrentModificationException异常 for (String string : list) { if("b".equals(string)) { list.remove("b"); } } System.out.println(list); } }
静态导入
格式:
* import static 包名….类名.方法名;
* 可以直接导入到方法的级别
注意事项
* 方法必须是静态的,如果有多个同名的静态方法,容易不知道使用谁?
* 这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
可变参数的概述和使用
* A:可变参数概述
* 定义方法的时候不知道该定义多少个参数
* B:格式
* 修饰符 返回值类型 方法名(数据类型 … 变量名){}
* C:注意事项:
* 这里的变量其实是一个数组
* 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
public class Demo9_ChangeableArgs { public static void main(String[] args) { int[] arr = {11,22,33,44,55}; //print(arr); System.out.println("-----------"); print(11,22,33,44,55); System.out.println("-----------"); //print(); } public static void print(int x,int ... arr) { for (int i : arr) { System.out.println(i); } } }
Arrays工具类的asList()方法的使用
数组转换成集合,虽然不能增加或减少元素,但是可以用集合的思想操作数组,也就是说可以使用其他集合中的方法
基本数据类型的数组转换成集合,会将整个数组当作一个对象转换,想将数组转换成集合,必须是引用数据类型。
//数组转集合 Integer[] arr = {11,22,33,44,55}; List<Integer> list = Arrays.asList(arr); System.out.println(list);
- Collection中toArray(T[] a)泛型版的集合转数组
String[] s = li.toArray(new String[0]);
当集合转换成数组时,数组长度如果是小于等于集合的size时,转换的数组长度等于集合的长度,如果数组的长度大于size,分配的数组长度就和你指定的长度一样。
//集合转数组 ArrayList<String> li = new ArrayList<>(); li.add("aa"); li.add("bb"); li.add("cc"); //数组长度如果是小于等于集合的size时,转换的数组长度等于集合的长度, //如果数组的长度大于size,分配的数组长度就和你指定的长度一样。 String[] s = li.toArray(new String[0]); for (String string : s) { System.out.println(string); }
集合嵌套之ArrayList嵌套ArrayList
import java.util.ArrayList; import com.zhangshan.bean.Person; public class Demo11 { public static void main(String[] args) { ArrayList<ArrayList<Person>> list = new ArrayList<>(); ArrayList<Person> one = new ArrayList<>(); one.add(new Person("王琪",22)); one.add(new Person("杨婷",24)); one.add(new Person("丹丹",25)); ArrayList<Person> two = new ArrayList<>(); two.add(new Person("张珊",14)); two.add(new Person("安琪",13)); two.add(new Person("盼盼",12)); list.add(one); list.add(two); for(ArrayList<Person> a:list ) { for(Person p: a) { System.out.println(p); } } } }
Java-集合(Collection,List(ArrayList,LinkedList,Vector))
原文:https://www.cnblogs.com/zheny98/p/14417394.html