集合数组
65.集合的由来和集合继承体系图
-集合的由来:数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
-数组和集合的区别:
1:
*数组既可以存储基本数据类型,也可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
*集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但在存储的时候会自动装箱为对象,100->new Integer(100)
2:
*数组的长度是固定的,不能自动增长
*集合的长度是可变的,可以根据元素的增加而增长
-集合和数组什么时候用:
*如果元素个数是固定推荐用数组,因为当使用集合时,由于集合也有通过数组实现的,所以在赋值时可能会产生大量垃圾,浪费内存
*如果元素个数不是固定的推荐用集合
-集合继承体系图:
66.Collection集合的基本功能
-方法:
boolean add(E e) //向集合中添加元素(参数为object的任意对象)
注:add方法如果是List集合一直会返回true,因为List集合是可以存储重复元素的,如果是Set集合存储重复元素就会返回false
boolean remove(Object o) //删除集合中的元素
void clear() //清空集合中的元素
boolean contains(Object o) //查看集合中是否包含指定元素,返回一个boolean值
boolean isEmpty() //判断集合是否为空
int size() //获取集合中元素的个数
-ArrayList的父类的父类重写toString方法,所以在打印对象引用的时候,输出的结果不是Object类中toString的结果
package Collection;
import java.util.ArrayList;
import java.util.Collection;
public class demo1 {
public static void main(String[] args) {
Collection c = new ArrayList(); //父类引用指向子类对象,编译看父类,运行看子类
boolean b1 = c.add("abc");
boolean b2 = c.add(true); //基本数据类型,会自动装箱,new Boolean(true);
boolean b3 = c.add(123); //new Integer(123)
boolean b4 = c.add(new Student("张三",23));
System.out.println(c);
}
}
67.集合的遍历
-遍历:其实就是依次获取集合中的每一个元素
-实现:将集合转换为数组,可以实现集合的遍历
方法:toArray(); //将集合转换为数组
package Collection;
import java.util.ArrayList;
import java.util.Collection;
public class demo2 {
public static void main(String[] args) {
demo1();
Collection c = new ArrayList();
c.add(new Student("张三",23)); //Object obj = new Student("张三",23); 向上转型 ,多态弊端无法使用子类特有的属性和方法
c.add(new Student("李四",24));
c.add(new Student("王五",25));
c.add(new Student("赵六",26));
Object[] arr = c.toArray(); //将集合转换为Object数组
for (int i = 0; i < arr.length; i++) {
//System.out.println(arr[i]); //它的作用只是为了显示
Student s = (Student)arr[i]; //将obj向下转型为Student对象,这样就可以使用student中特有的属性和方法
System.out.println(s.getName()+".."+s.getAge()); //这样不仅可以显示,还可以获取数据做其他操作
}
}
private static void demo1() {
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Object[] arr = c.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
68.Collection集合中带All的方法测试
-方法:
boolean addAll(Collection c) //将整个集合添加为另一集合的元素中,合并
boolean removeAll(Collection c) //删除的是交集
boolean containsAll(Collection c) //判断一集合是否包含另一集合的元素,可以重复,但如果另一集合含有集合中不存在的元素,则返回fasle
boolean retainAll(Collection c) //获取两个集合的交集,如果调用的集合改变就返回true,如果调用的集合不变就返回false
package Collection;
import java.util.ArrayList;
import java.util.Collection;
public class demo3 {
public static void main(String[] args) {
addAll();
removeAll();
containsAll();
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("b");
boolean b = c1.retainAll(c2);
Collection c3 = new ArrayList();
c3.add("a");
c3.add("b");
c3.add("c");
c3.add("d");
c3.add("e");
c3.add("f");
System.out.println("获取c1,c2中相同的元素,若c1改变,返回true若不变,返回false");
System.out.println(b);
System.out.println(c1);
System.out.println("c3包含c1的全部元素,此时c1不变,返回false");
boolean b2 = c1.retainAll(c3);
System.out.println(b2);
System.out.println(c1);
}
private static void containsAll() {
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("b");
boolean b = c1.containsAll(c2);
System.out.println("判断c1中是否含有c2中的所有元素,c2中的元素可以重复,但如果含有c1没有的元素,则返回false");
System.out.println(b);
System.out.println(c1);
}
private static void removeAll() {
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("3");
boolean b = c1.removeAll(c2);
System.out.println("获取两个集合的交集,若没有交集则返回false");
System.out.println(b);
System.out.println(c1);
}
private static void addAll() {
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("3");
boolean b = c1.addAll(c2);
System.out.println("将两个集合合并,并将结果返回给调用的集合");
System.out.println(b);
System.out.println(c1);
}
}
69.集合的遍历之迭代器遍历
-概述: 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
-迭代器:Iterator(接口)
-迭代器原理:迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可
-方法:
*boolean hasnext() //如果仍有元素可以迭代,返回true
*next() //返回迭代的下一个元素
package Collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class demo4 {
public static void main(String[] args) {
demo1();
Collection c = new ArrayList();
c.add(new Student("张三",23)); //Object obj = new Student("张三",23); 向上转型 ,多态弊端无法使用子类特有的属性和方法
c.add(new Student("李四",24));
c.add(new Student("王五",25));
c.add(new Student("赵六",26));
Iterator it = c.iterator(); //获取迭代器
while(it.hasNext()){
Student s = (Student)it.next(); //将集合中的元素向下转型,由object对象转换为Student对象
System.out.println(s.getName()+".."+s.getAge());
}
}
private static void demo1() {
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Iterator it = c.iterator(); //获取迭代器
while(it.hasNext()){
System.out.println(it.next()); //指针会自动向后移动
}
}
}
70.List集合的特有功能概述
-概述:有序的Collection也称为序列,此接口的用户可以对列表中每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引访问元素,并搜索列表中的元素。
-方法:
* void add(int index,E element) //在列表的指定位置插入元素
* E remove(int index) //删除指定位置的元素
* E get(int index) //根据索引获取指定元素
* E set(int index,E element) //修改指定位置的元素
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class demo5_List {
public static void main(String[] args) {
add();
remove();
get();
set();
}
private static void set() {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.set(1, "x");
System.out.println(list);
}
private static void get() {
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
//利用迭代器遍历List集合
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//通过索引遍历List集合
for(int i=0;i=0都不会触发异常
//list.add(10,"e"); IndexOutOfBoundsException索引越界异常
System.out.println(list);
}
}
-List集合的遍历
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class demo6 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Student("张三",23));
list.add(new Student("李四",24));
list.add(new Student("王五",25));
list.add(new Student("赵六",26));
//利用get方法遍历
for (int i = 0; i < list.size(); i++) {
//System.out.println(list.get(i));
Student s = (Student)list.get(i);
System.out.println(s.getName()+".."+s.getAge());
}
System.out.println();
//利用迭代器遍历
Iterator it = list.iterator();
while(it.hasNext()){
Student s = (Student)it.next(); //将obj对象向下转型,这样就可以使用student类中特有的属性和方法
System.out.println(s.getName()+".."+s.getAge());
}
}
}
-并发修改异常产生的原因及解决方案
-ListIterator接口:系列表迭代器,允许按任一方法遍历集合,迭代期间修改列表,接口中有add方法,可以在迭代期间向列表添加元素,而不触发并发修改异常(ConcurrentModificationException)的错误
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class demo7_listIterator {
public static void main(String[] args){
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("hello");
list.add("c");
list.add("d");
/*Iterator it= list.iterator(); //获取迭代器
while (it.hasNext()) { //判断集合是否有元素
String s = (String)it.next(); //向下转型
if("hello".equals(s)){ //如果集合中含有"hello"字符串,就向集合中添加world
list.add("wolrd"); //遍历的同时再增加元素,不允许在遍历期间修改集合,触发ConcurrentModificationException异常(并发修改异常)
}
}*/
ListIterator lit = list.listIterator();
while (lit.hasNext()) { //判断集合是否有元素
String s = (String)lit.next(); //向下转型
if("hello".equals(s)){ //如果集合中含有"hello"字符串,就向集合中添加world
lit.add("wolrd"); //调用 ListIterator接口中的add方法,允许再遍历期间修改集合
}
}
System.out.println(list);
}
}
-ListIterator接口功能
* boolean hasNext() 是否有下一个
* boolean hasPrevious() 是否有前一个
* Object next() 返回下一个元素
* Object previous() 返回上一个元素
71.Vector接口的概述
-概述:实现了List接口,功能被ArrayList取代
-特有功能:
未实现List接口时,Vector通过枚举来遍历获取集合中的值
*void addElement(obj E) 添加元素
-Enumeration 枚举对象,实现枚举功能
*hasMoreElements() 测试此枚举是否包含更多的元素
*nextElement() 如果还有下一个对象,返回下一个元素
package Collection;
import java.util.Enumeration;
import java.util.Vector;
public class demo8_Vector {
public static void main(String[] args) {
Vector v = new Vector();
v.addElement("a");
v.addElement("b");
v.addElement("c");
v.addElement("d");
Enumeration en = v.elements(); //获取枚举
while(en.hasMoreElements()){ //判断是否有元素
System.out.println(en.nextElement()); //输出集合中的所有元素
}
}
}
72.List的三个子类
-数组与链表的比较:
数组:查询快修改也快
增加和删除慢
链表:查询慢修改也慢
增加和删除快
-ArrayList,LinkList,Vector的比较:
*ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
*Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
*1.Vector相对ArrayList查询慢(线程安全的)
*2.Vector相对LinkedList增删慢(数组结构)
*LinkedList:
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
*Vector和ArrayList的区别:
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
*ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
73.ArrayList去重
-思路:1.创建新集合接收老集合中不重复的值
2.获取老集合中的迭代器
3.遍历老集合
4.通过新集合是否包含老集合中的元素,如果包含就不添加,不包含就添加
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class demo9_ArrayList去重 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("a");
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("b");
list.add("c");
list.add("c");
list.add("b");
ArrayList li = method(list);
System.out.println(li);
}
public static ArrayList method(ArrayList list){
ArrayList al = new ArrayList(); //创建新集合
Iterator it = list.iterator(); //获取传入集合的迭代器
while(it.hasNext()){
Object obj = it.next(); //取得集合中每一个元素
if(!al.contains(obj)){ //如果新集合不包含obj,就添加
al.add(obj);
}
}
return al;
}
}
-自定义类实现去重
-注意点:Contains方法和remove方法底层是通过equals方法实现的,如果自定义类没有重写equals方法的话,就会调用object类的equals方法,此时比较的是对象的地址值。
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
public class demo9_ArrayLIst2 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(new Student("张三",23));
list.add(new Student("张三",23));
list.add(new Student("张三",25));
list.add(new Student("李四",24));
list.add(new Student("李四",24));
ArrayList al = method(list);
System.out.println(al);
}
public static ArrayList method(ArrayList list){
ArrayList aList = new ArrayList(); //创建新集合
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
if(!aList.contains(obj)){ //Contains底层是通过equals实现的,如果自定义类没有重写equals方法,就会自动调用object类的equals方法,此时比较的是地址值
aList.add(obj);
}
}
return aList;
}
}
Student类:
@Override //重写equals方法
public boolean equals(Object obj) {
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.age;
}
75.LinkedList的概述及使用
-概述:List接口的链表形式实现
-链表:查询和修改慢,增加和删除快,因为链表的每一个元素(除开头和结尾外)都保留着它前一个元素和后一个元素的地址,这样就可以以链的形式连接,但查询时,只能从头或从尾依次查找,直至找到,所以查询慢,而删除时只要将两个元素之间的链去掉即可。
-方法:
* public void addFirst(E e)及addLast(E e) //在链的头部或尾部添加元素
* public E getFirst()及getLast() //获取链的头部或尾部的元素
* public E removeFirst()及public E removeLast() //删除链的头部或尾部的元素
* public E get(int index) //获取指定索引的元素,由(index和size/2)比较,判断应从头部还是尾部开始查找
-用LinkedList模拟栈数据结构
package Collection;
import java.util.LinkedList;
public class demo11_stack {
private LinkedList list = new LinkedList();
public static void main(String[] args) {
demo11_stack d = new demo11_stack();
d.inStack("a");
d.inStack("b");
d.inStack("c");
d.inStack("d");
while(!d.isEmpty()){
System.out.println(d.outStack());
}
}
public void inStack(Object obj){
list.addFirst(obj);
}
public Object outStack(){
return list.removeFirst();
}
public boolean isEmpty(){
return list.isEmpty();
}
}
77.增强for概述及其使用
-概述:简化数组及Collection集合的遍历(底层用迭代器实现)
-格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
package generic;
import java.util.ArrayList;
public class demo5_foreach {
public static void main(String[] args) {
int arr[] = {11,22,33,44,55};
for (int i : arr) {
System.out.println(i);
}
ArrayList< String > list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
for (String string : list) {
System.out.println(string);
}
}
}
78.三种迭代的能否删除
package generic;
import java.util.ArrayList;
import java.util.Iterator;
public class demo6 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");
//for 循环遍历删除指定元素
/*for (int i = 0; i < list.size(); i++) {
if("b".equals(list.get(i))){ //找到"b"
list.remove(i--); //删除"b",并使索引回退一位,因为当删除一个元素时,list的size会减少一位,此时如果i的索引不减一的话,就会跳过删去元素的下一位元素
}*/
//迭代器循环遍历删除指定元素
/*Iterator it = list.iterator();
while (it.hasNext()) {
if("b".equals(it.next())){
it.remove();
//list.remove("b"); 不能用集合的修改方法,因为会出现并发修改异常
}
}*/
//foreach循环遍历删除(不可以)因为foreach底层依赖迭代器实现
/*for (String string : list) {
if("b".equals(string)){
list.remove("b"); //并发修改异常,不能删除指定元素
}
}*/
}
}
79.静态导入
-概述:静态导入类方法
-格式:import static 包名... 类名.方法名
可以直接导入到方法的级别
-注意事项:方法必须是静态的,但如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。
80.可变参数
-概述:当定义方法的时候不知道应该定义多少个参数
-格式:
*修饰符 返回值类型 方法名(数据类型 ... 变量名){}
-注意事项:
*这里的可变参数其实是一个数组
*如果一个方法有可变参数,并且还有多个参数,可变参数肯定是最后一个
package generic;
public class demo7_changeableargs {
public static void main(String[] args) {
String[] arr = {"a","b","c","d"};
method("s1","z","x","y");
}
public static void method(String s1,String ... arr1){
for (String string : arr1) {
System.out.println(string);
}
}
}
81.asList方法
-功能:将数组转换成集合
-注意:
*数组转换成集合后不能增加或删除元素,但是可以用集合的思想来操作数组,也就是说可以使用其他集合里的方法
*基本数据类型转数组,会将整个数组转化为一个对象
*将数组转化为集合,数组必须是引用数据类型
package Arrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class demo2_asList {
public static void main(String[] args) {
Integer[] arr = {11,11,22,33,33,44,44,55};
List list = Arrays.asList(arr);
System.out.println(list); //数组转集合只能是引用数据类型
listtoarray();
}
private static void listtoarray() {
ArrayList list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
String[] arr = list.toArray(new String[5]); //当集合转数组时,数组的长度如果<=size,转换后的数组长度等于集合的size,如果>size,那么数组的长度就和你指定的长度一样
for (String string : arr) {
System.out.println(string);
}
}
}
82.集合中嵌套集合
package Collection;
import java.util.ArrayList;
public class demo12 {
public static void main(String[] args) {
ArrayList> list = new ArrayList<>();
ArrayList First = new ArrayList<>();
First.add(new Student("张三",23));
First.add(new Student("李四",24));
First.add(new Student("王五",25));
ArrayList Second = new ArrayList<>();
Second.add(new Student("赵六",26));
Second.add(new Student("周七",27));
Second.add(new Student("潘八",28));
list.add(First);
list.add(Second);
for (ArrayList as :list ) {
System.out.println(as);
for (Student s : as) {
System.out.println(s);
}
}
}
}