ArrayList集合是程序中最常见的一种集合,它属于引用数据类型(类)。在ArrayList内部封装了一个长度可变的数组,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。
导包:import java.util.ArrayList;
创建对象:与其他普通的引用数据类型创建方式完全相同,但是要指定容器中存储的数据类型:
ArrayList<要存储元素的数据类型> 变量名 = new ArrayList<要存储元素的数据类型>();
下面给出8种基本数据类型所对应的引用数据类型表示形式:
我们通过举几个例子,来明确集合的创建方式:
ArrayList<String> list = new ArrayList<String>();
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<Phone> list = new ArrayList<Phone>();
package cn.jxufe.java.chapter6; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestArrayList01 { public static void main(String[] args) { // TODO Auto-generated method stub // 创建ArrayList集合 ArrayList<String> list1 = new ArrayList<String>();// 第二个可以省略 // 向集合中添加元素 list1.add("stu1"); list1.add("stu2"); list1.add("stu3"); list1.add("stu4"); // 获取集合中元素的个数 // 取出并打印指定位置的元素 System.out.println("第2个元素是:" + list1.get(1)); System.out.println("list1中的元素为:"); System.out.println(list1); System.out.println("去除索引值为2的元素后,list中的元素为"); list1.remove(2); System.out.println(list1); System.out.println("在索引值为1的元素处添加一个student元素:"); list1.add(1, "student"); System.out.println(list1); System.out.println("把索引位置为3的元素置为good:"); list1.set(3, "good"); System.out.println(list1); // 集合的遍历 System.out.println("集合的遍历方法1:"); for (String e : list1) { System.out.print(e + " "); } System.out.println("\n集合的遍历方法2: "); for (int i = 0; i < list1.size(); i++) { System.out.print(list1.get(i) + " "); } System.out.println("\nlist1是否为空:"); System.out.println(list1.isEmpty()); System.out.println("list1是否包涵good:"); System.out.println(list1.contains("good")); ArrayList<String> list2 = new ArrayList<>(); list2.add("stu1"); list2.add("stu2"); System.out.println("list2中的元素为:"); System.out.println(list2); System.out.println("从list1中移除list2中的全部元素"); list1.removeAll(list2);// 获得两个集合元素的差集 System.out.println(list1); System.out.println("list1添加list2中的全部元素"); list1.addAll(list2);// 获得两个集合元素的并集 System.out.println(list1); List<String> list3 = new ArrayList<String>(); list3.add("第一个元素"); // 向列表中添加数据 list3.add("第二个元素"); // 向列表中添加数据 list3.add("第三个元素"); // 向列表中添加数据 List<String> list4 = new ArrayList<String>(); list4.add("第一个元素"); // 向列表中添加数据 list4.add("第三个元素"); // 向列表中添加数据 System.out.println("--------测试retainAll的使用------------:"); boolean ret = list3.retainAll(list4); // 获得两集合相交的元素 System.out.println(ret); System.out.println(list3); // 创建迭代器 Iterator<String> it = list3.iterator(); // 循环遍历迭代器 System.out.println("循环遍历迭代器:"); while (it.hasNext()) { System.out.println(it.next()); // 输出集合中元素 } ArrayList<String> list5 = new ArrayList<>(); ArrayList<String> list6 = new ArrayList<>(); list5.add("a"); list5.add("b"); list5.add("c"); list6.add("b"); list6.add("c"); list6.add("d"); list5.retainAll(list6);// 获得两集合相交的元素 System.out.println(list5); } }
查看ArrayList类发现它继承了抽象类AbstractList同时实现接口List,而List接口又继承了Collection接口。Collection接口为最顶层集合接口了。
源代码: interface List extends Collection { } public class ArrayList extends AbstractList implements List{ }
集合继承体系
这说明我们在使用ArrayList类时,该类已经把所有抽象方法进行了重写。那么,实现Collection接口的所有子类都会进行方法重写。
java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。
Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
package cn.jxufe.java.chapter6; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class TestIterator03 { /* * 集合中的迭代器: 获取集合中元素方式 接口 Iterator : 两个抽象方法 boolean hasNext() * 判断集合中还有没有可以被取出的元素,如果有返回true next() 取出集合中的下一个元素 * * Iterator接口,找实现类. Collection接口定义方法 Iterator iterator() ArrayList * 重写方法iterator(),返回了Iterator接口的实现类的对象 使用ArrayList集合的对象 Iterator * it=array.iterator(),运行结果就是Iterator接口的实现类的对象 it是接口的实现类对象,调用方法 hasNext 和 next * 集合元素迭代 */ public static void main(String[] args) { // TODO Auto-generated method stub Collection<String> coll = new ArrayList<String>(); coll.add("abc1"); coll.add("abc2"); coll.add("abc3"); coll.add("abc4"); // 迭代器,对集合ArrayList中的元素进行取出 // 调用集合的方法iterator()获取出,Iterator接口的实现类的对象 Iterator<String> it = coll.iterator(); // 接口实现类对象,调用方法hasNext()判断集合中是否有元素 // boolean b = it.hasNext(); // System.out.println(b); // 接口的实现类对象,调用方法next()取出集合中的元素 // String s = it.next(); // System.out.println(s); // 迭代是反复内容,使用循环实现,循环的条件,集合中没元素, hasNext()返回了false while (it.hasNext()) { String s = it.next(); System.out.println(s); } System.out.println(); // for循环的方式进行遍历,for没有while好理解,但是节约点内存,因为while的it是在main函数中建立的,for的it是在for中建立的 for (Iterator<String> it2 = coll.iterator(); it2.hasNext();) { System.out.println(it2.next()); } } }
存储时提升了Object。取出时要使用元素的特有内容,必须向下转型。
package cn.jxufe.java.chapter6; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class TestCollection04 { public static void main(String[] args) { // TODO Auto-generated method stub Collection coll = new ArrayList(); coll.add("abc"); coll.add("aabbcc"); coll.add("shitcast"); Iterator it = coll.iterator(); while (it.hasNext()) { // 由于元素被存放进集合后全部被提升为Object类型 // 当需要使用子类对象特有方法时,需要向下转型 String str = (String) it.next(); System.out.println(str.length()); } // 注意:如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。 } }
在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。比如下面程序:
package cn.jxufe.java.chapter6; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestGeneric05 { public static void main(String[] args) { // TODO Auto-generated method stub List list = new ArrayList(); list.add("abc"); list.add("itcast"); list.add(5);// 由于集合没有做任何限定,任何类型都可以给其中存放 // 相当于:Object obj=new Integer(5); Iterator it = list.iterator(); while (it.hasNext()) { // 需要打印每个字符串的长度,就要把迭代出来的对象转成String类型 String str = (String) it.next();// String str=(String)obj; // 编译时期仅检查语法错误,String是Object的儿子可以向下转型 // 运行时期String str=(String)(new Integer(5)) // String与Integer没有父子关系所以转换失败 // 程序在运行时发生了问题java.lang.ClassCastException System.out.println(str.length()); } } }
泛型: 指明了集合中存储数据的类型 <数据类型>
上面已经使用了
泛型只在编译时存在,编译后就被擦除,在编译之前我们就可以限制集合的类型,起到作用
例如:ArrayList<String> al=new ArrayList<String>();
编译后:ArrayList al=new ArrayList();
a:定义格式:
修饰符 class 类名<代表泛型的变量> { } 例如,API中的ArrayList集合: class ArrayList<E>{ public boolean add(E e){ } public E get(int index){ } }
b:使用格式:
创建对象时,确定泛型的类型 例如,ArrayList<String> list = new ArrayList<String>(); 此时,变量E的值就是String类型 class ArrayList<String>{ public boolean add(String e){ } public String get(int index){ } } 例如,ArrayList<Integer> list = new ArrayList<Integer>(); 此时,变量E的值就是Integer类型 class ArrayList<Integer>{ public boolean add(Integer e){ } public Integer get(int index){ } }
package cn.jxufe.java.chapter6; import java.util.ArrayList; public class GenericStack07<E> { ArrayList<E> list = new ArrayList<>(); public int getSize() { return list.size(); } public E peek() { return list.get(getSize() - 1); } public E pop() { E o = list.get(getSize() - 1); list.remove(getSize() - 1); return o; } public boolean isEmpty() { return list.isEmpty(); } public void push(E e) { list.add(e); } @Override public String toString() { // TODO Auto-generated method stub return "stack: " + list.toString(); } public static void main(String[] args) { GenericStack07<String> stack1 = new GenericStack07<>(); stack1.push("good"); stack1.push("good"); stack1.push("study"); System.out.println(stack1); GenericStack07<Integer> stack2 = new GenericStack07<>(); stack2.push(123); stack2.push(456); stack2.push(789); System.out.println(stack2); } }
a:定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
b:泛型方法的使用:
例如,API中的ArrayList集合中的方法: public <T> T[] toArray(T[] a){ } //该方法,用来把集合元素存储到指定数据类型的数组中,返回已存储集合元素的数组 使用格式:调用方法时,确定泛型的类型 例如: ArrayList<String> list = new ArrayList<String>(); String[] arr = new String[100]; String[] result = list.toArray(arr); 此时,变量T的值就是String类型。变量T,可以与定义集合的泛型不同 public <String> String[] toArray(String[] a){ } 例如: ArrayList<String> list = new ArrayList<String>(); Integer[] arr = new Integer[100]; Integer [] result = list.toArray(arr); 此时,变量T的值就是Integer类型。变量T,可以与定义集合的泛型不同 public <Integer> Integer[] toArray(Integer[] a){ }
/* * 带有泛型的接口 * * public interface List <E>{ * abstract boolean add(E e); * } * * 实现类,先实现接口,不理会泛型 * public class ArrayList<E> implements List<E>{ * } * 调用者 : new ArrayList<String>() 后期创建集合对象的时候,指定数据类型 * * * 实现类,实现接口的同时,也指定了数据类型 * public class XXX implements List<String>{ * } * new XXX() */
可以使用非受限通配、受限通配或者下限通配来对一个泛型类型指定范围。
package cn.jxufe.java.chapter6; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class TestWildcard06 { public static void main(String[] args) { // TODO Auto-generated method stub ArrayList<String> array = new ArrayList<String>(); HashSet<Integer> set = new HashSet<Integer>(); array.add("123"); array.add("456"); set.add(789); set.add(890); iterator(array); iterator(set); } /* * 定义方法,可以同时迭代2个集合 参数: 怎么实现 , 不能写ArrayList,也不能写HashSet 参数: 或者共同实现的接口 * 泛型的通配,匹配所有的数据类型 ? */ public static void iterator(Collection<?> coll) { Iterator<?> it = coll.iterator(); while (it.hasNext()) { // it.next()获取的对象,什么类型 System.out.println(it.next()); } }
}
原文:https://www.cnblogs.com/xinmomoyan/p/10946311.html