集合:
-
容器:数组,字符串缓冲区
- 数组作为容器:增加、删除数组中元素不方便;
- 可以存储基本数据类型,引用数据类型;
- 一旦定义长度不可变;
- 只能存储同一种数据类型:
- 集合:为了更方便的去操作数组容器中的元素(增,删,改,查);
- 只能存储引用类型;
- 长度可变;
- 可以存储多种引用数据类型;
- Collection 接口 是单列集合 顶层父接口
- List 子接口
- ArrayList 实现类
- 数组(底层数据结构使用)
- 查询快,增删慢 线程不安全,效率高;
- 数组(底层数据结构使用)
- LinkedList 实现类
- 链表
- 查询慢,增删快
- 链表
- Vector 实现类
- 数组
- 查询快,增删慢 线程安全,效率低;
- 数组
- ArrayList 实现类
- set 子接口
- HashSet 实现类 哈希表
- LinkedHashSet 实现类 链表 哈希表
- TreeSet 实现类
- List 子接口
//Collection方法: //add() 添加:往集合中添加元素,返回值代表是否添加成功 Collection collection = new ArrayList();//多态 boolean b = collection.add("abx"); //addAll() 把两个集合中的元素放到一个集合 Collection collection1 = new ArrayList(); Collection collection2 = new ArrayList(); collection1.add(100); //自动装箱 collection2.add("asd"); boolean b = collection1.addAll(collection2); //remove() 删除 Collection collection = new ArrayList(); collection.add(100); //自动装箱 boolean b = collection.remove(100); //removeAll() 移除交集元素 有交集删除collection1中交集元素,返回true无交集元素,返回false Collection collection1 = new ArrayList(); Collection collection2 = new ArrayList(); collection1.add(100); //自动装箱 collection2.add("100"); boolean b = collection1.removeAll(collection2); //clear(); 清空所有 //contains(): 判断集合中是否包含该元素 boolean b = collection.contains(100); //containsAll(); 判断集合1是否完全包含集合2,若包含输出true 否则为false Collection collection1 = new ArrayList(); Collection collection2 = new ArrayList(); collection1.add(100); //自动装箱 collection2.add(100); boolean b = collection1.containsAll(collection2); //判断一个集合是否为空 boolean b = collection.isEmpty(); //获取集合的长度: .size(); int size = collection.size(); ************************* //遍历: //需要获取一个迭代器 interator(); Interator interator = collection.interator(); while(interator.hasNext()){ Object obj = iterator.next(); //返回迭代的下一个元素 } //取两个集合中元素交集,并且对于collection1只保留交集元素, //返回值表示集合是否发生改变,若改变则为true,否则为false Collection collection1 = new ArrayList(); Collection collection2 = new ArrayList(); collection1.add(100); //自动装箱 collection2.add(100); boolean b = collection1.retainAll(collection2); //把一个集合转化为数组: Collection collection = new ArrayList(); collection.add(100); collection.add(200); collection.add(300); Integer[] integers = new Integer[collection.size()]; Iterator iterator = collection.iterator(); int i = 0; while(iterator.hasNext()){ Object next = iterator.next(); Integer integer = (Integer)next; integers[i++] = integer; } System.out.println(Arrays.toString(integers)); //把数组转化为集合:
$ 内部类
//List接口特有的方法: List list = new ArrayList(); //void add(int index, E element) 在指定索引出添加元素 list.add(0, 20000); //根据索引获取元素: //根据其实索引终止索引,截取一段元素放到新集合中; //根据索引修改元素: //移除列表中指定位置的元素 set(int index); list.remove(2); //根据索引删除 list.remove(Integer.valueOf(2000)); //假如是Integer类型,要删除的时候,区分不出来,
//遍历方式1: list.iterator(); //便利方式2: ListIterator listIterator = list.listIterator(); //遍历方式3:for循环 for(int i = 0; i < list.size(); i++){ Object o = list.get(i); System.out.println(o); }
ListIterator 如果没有先进行正向迭代,无法进行反向迭代; 是因为正向迭代将指针已经移动到最下边,反向迭代往上的时候,就有了可以迭代的元素;
ConcurrentModificationException 并发修改法异常 //当你使用迭代器,对集合的元素,进行迭代,那么在迭代途中,先要增删集合中的元素,就会出现并发修改异常 //是因为通过集合获取到迭代器后,迭代器已经预先知道集合中元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,若突然增删元素,就会打乱迭代器迭代顺序,就会跑出并发修改异常; //解决方法1: 使用迭代器,遍历,那么在遍历途中,想要增删元素,那么就是用迭代器中自带的增删元素办法; listIterator.add(); //解决方法2: 使用for循环
数据结构:一种存储数据的方式,为了提高存储和运行的效率; 常见的数据结构: * 数组: * 查询快(有索引);增删慢(需要新建数组); * 链表: * 查询慢(从头开始查询);增删快(只需要改变地址域); * 栈: * 先进后出; * 队列: * 先进先出; * 哈希: * 二叉树:
- ArrayList特有方法:
ArrayList list = new ArrayList(); list.add(100); list.add(200); list.add(300); list.add(400); list.add(500); //lastIndexOf(); 根据元素查找该元素第一次出现的索引,从后往前 int index = list.lastIndexOf(100); //indexOf();根据元素查找该元素第一次出现的索引,从前往后 int index = list.indexOf(100); //foreach(); for(int i = 0; i < list.size(); i++){ System.out.println(list.get(i)); } //Consumer //遍历集合中的元素 list.forEach(new Consumer){ @Override public void accept(Object o){ System.out.println(o); } } //可以使用Lambda简化上面写法: list.forEach((obj)->System.out.println(obj));
- vector特有方法:
Vector vector = new Vector(); //addElement(Object obj); //增添元素 //element(int index); //查找元素 //elements(); 返回一个迭代器,Enumeration
- LinkedList特有方法:
LinkedList linkenList = new LinkedList(); //addFirst(E e) 往前添加 //addLast(E e) 往后添加 //getFirst() 拿出第一个元素 //getLast() 拿出最后一个元素 //removeFirst() 删除第一个元素 //removeLast() 删除最后一个元素 //peak() 查询第一个元素,并返回 //peakFirst() 查询第一个元素,并返回 //poll() 检索并删除第一个元素
- 数组作为容器:增加、删除数组中元素不方便;
泛型
-
使用泛型就可以明确集合中放的是什么数据类型;
-
泛型机制:是JDK1.5引入的,是一种将数据类型明确规定,推迟了创建对象,或调用方法时,再去明确的一种机制;
-
语法:泛型可以使用在类、接口、方法上
-
格式:<引用类型,引用类型…>
-
优点:将问题提前到了编译期,避免了向下转型;提高代码的扩展性;
-
只在编译期有效
//明确了泛型的基本类型,那么这个集合只能存储这种类型
ArrayList<String> string = new ArrayList<String>();
- 泛型类:设计一个泛型类,给类加上泛型
- 格式:class A{}
public class MyDemo<T>{
//T泛型(用大写字母代替)
private T obj;
public T getObj(){
return obj;
}
publiv void setObj(T obj){
this.obj = obj;
}
}
-
泛型接口
//在接口使用泛型 interface MyInterface<T>{ T set(T t); }
-
明确泛型接口:
-
实现的时候;可以明确接口上的泛型到底是什么类型;
class Son implements MyInterface<String>{ @Override public String (String s){ return null; } }
-
匿名内部类的时候;
new MyInterface<Intger>(){ @Override public Integer set(Integer integer){ return null; } }
-
-
-
泛型方法
- 在调用方法时候明确;
class AA{
public void set(String str){
}
public Integer set(Integer str){
}
}
改进入下:
class AA{
public void set(Object str){
}
}
需要向下转型:
继续改进
//泛型方法:
class AA{
public<P> void set(P str){
}
}
-
通配符:? <?>
-
向上限定
ArrayList<? super Animal> object = new ArrayList<Animal>(); ArrayList<? super Animal> object = new ArrayList<Object>();
-
向下限定
ArrayList<? extends Animal> object = new ArrayList<Animal>(); ArrayList<? extends Animal> object = new ArrayList<Dog>(); ArrayList<? extends Animal> object = new ArrayList<Cat>();
-
增强for循环
- 遍历集合
int[] arr = {20, 20, 30, 80}; //遍历方式 //for(容器中元素的类型 当前元素变量名: 容器名(数组/集合)){ // System.out.println(当前元素变量名) //} for(int ele: arr){ System.out.println(ele); }
- 需要索引做判断,用普通for循环;
- 只是遍历容器,用增强for循环;
- 增强for循底层用的是迭代器在进行迭代,遍历过程中,不能对元素进行增删;否则会出现并发修改异常;
-
可变参数:
- 一次可以接受多个参数
- 本质:数组
//数据类型 ... 参数名 private static int add(int ... num){ int sum = 0; for(int i: num){ sum += i; } retrun sum; } //若一个方法上,有普通参数,有可变参数,可变参数放最后面,可以有两种不同类型可变参数;
-
把集合转成数组
// Arrays 数组工具类 // List // 把集合转成数组 Object[] obj = new ArrayList<Integert>().toArray(); //把一个数组转换成集合 static<T> List<T> asList(T ... a) //返回一个受指定数组支持的固定大小的列表 Integer[] integers = {20 ,30 ,40 , 50}; //如果给该方法传入的是一个引用类型数组,那么他会取出该数组中的元素,放到集合中, List<Integer> integers1 = Arrays.asList(integers); for(Integer integer : integers1){ System.out.println(integer); } //假如传入两个以上的数组,它是将数组对象作为元素放入集合中, Integer[] integers2 = {20, 30, 40, 50}; Integer[] integers3 = {20, 30, 40, 50}; List<Integer[]> integers4 = Arrays.asList(integers2, integers3); System.out.println(integers4); //输出的是两个数组对象 Integer integer = integer4.get(0)[0]; //取出第一个数组中的第一个元素; //当你传入一个基本类型数组,转换成集合,集合放的是数组对象 int[] ints = {20, 30, 50 ,60}; List<int[]> ints1 = Arrrays.asList(ints); int[] ints2 = ints1.get(0); //输出的是一个int类型数组的对象 int[] ints3 = {20, 30, 50 ,60}; int[] ints4 = {20, 30, 50 ,60}; List<int[]> ints5 = Arrays.asList(ints3, ints4); //输出的是两个数组对象 //asList(20, 30, 40); 通过这个方法转换过来的集合,只能对集合中的元素进行查询和修改;转换过来的集合,长度不可变; Lisr<Integer> list = Arrays.asList(20, 30, 40);
package www.sd.day15;
import java.util.ArrayList;
public class Test2 {
public static void main(String[] args) {
ArrayList<Student> javaList = new ArrayList<>();
javaList.add(new Student("张一", 20));
javaList.add(new Student("张二", 21));
javaList.add(new Student("张三", 22));
ArrayList<Student> webList = new ArrayList<>();
webList.add(new Student("李一", 20));
webList.add(new Student("李二", 21));
webList.add(new Student("李三", 24));
ArrayList<Student> linuxList = new ArrayList<>();
linuxList.add(new Student("赵一", 20));
linuxList.add(new Student("赵二", 21));
linuxList.add(new Student("赵三", 23));
//我站在西开的角度,我要存储这个三个班
ArrayList<ArrayList<Student>> westosList = new ArrayList<>();
westosList.add(javaList);
westosList.add(webList);
westosList.add(linuxList);
//遍历每一个学生的信息
//普通for
for (int i = 0; i < westosList.size(); i++) {
for (int j = 0; j < westosList.get(i).size(); j++) {
Student student = westosList.get(i).get(j);
System.out.println(student.getName()+"==="+student.getAge());
}
}
//曾强for
for(ArrayList<Student> minList: westosList){
for(Student student: minList){
System.out.println(student.getName()+"==="+student.getAge());
}
}
}
}