Collection集合
数组作为容器,对容器中的元素的操作不是很方便,所以Java为了我们更方便的去操作容器中的元素,给我们提供了另一种容器,叫做集合
集合和数组的区别
1.数组的长度是固定的,集合的长度是可变的
2.数组可以存储基本数据类型,也可以存储引用数据类型,集合只能存储引用数据类型
3.数组只能存储同一种数据类型,集合可以存储多种数据类型
集合中的常用方法
a:添加功能
boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
b:删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素
如果没有交集元素 则删除失败 返回false
c:判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
比如:1,2,3 containsAll 12=true 1,2,3 containsAll 2,3,4=false
boolean isEmpty():判断集合是否为空
d:获取功能
Iterator iterator()(重点)
e:长度功能
int size():元素的个数
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
f:交集功能
//例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化
boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
g:把集合转换为数组
Object[] toArray()
List集合
List 集合的特点:元素有序(存取顺序一致),允许重复元素
public class lianxi {
public static void main(String[] args) {
List list = new ArrayList();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
list.add(0,1);//可以在指定的索引处插入元素
//遍历 方式一
// Iterator iterator = list.iterator();
// while (iterator.hasNext()){
// System.out.println(iterator.next());
// }
方式二
// for (int i = 0; i < list.size(); i++) {
// Object o = list.get(i);
// System.out.println(o);
// }
//方式三
// ListIterator listIterator = list.listIterator();
// while (listIterator.hasNext()){
// System.out.println(listIterator.next());
// }
// //反向遍历 ,用同一个迭代器,先正向遍历完,才能反向遍历,直接反向遍历没效果,因为指针还在起始位置
// while (listIterator.hasPrevious()){
// System.out.println(listIterator.previous());
// }
//方式四 强循化
for (Object o :list ){
System.out.println(o);
}
}
}
注意:我们用Iterator这个迭代器遍历采用hasNext方法和next方法,集合修改集合 会出现并发修改异常
原因是我们的迭代依赖与集合 当我们往集合中添加好了元素之后 获取迭代器 那么迭代器已经知道了集合的元素个数,这个时候你在遍历的时候又突然想给 集合里面加一个元素(用的是集合的add方法)那迭代器不同意 就报错了
public class lianxi {
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc");
list.add("ABC");
list.add("CBA");
list.add("NBA");
// list.add(0,"JAC");//可以在指定的索引处插入元素
// list.set(list.size()-1,"WWE");
// Iterator iterator = list.iterator();
// while (iterator.hasNext()){
// Object o = iterator.next();
// String str=(String)o;
// if ("NBA".equals(str)){
// list.add("Java");
// }
//
}
// //方式一 不用迭代器遍历
// for (int i = 0; i < list.size(); i++) {
// Object o = list.get(i);
// String str=(String)o;
// if ("NBA".equals(str)){
// list.add("Java");
// }
// }
// System.out.println(list);
// 方式二 使用自带的迭代器遍历
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
Object o = listIterator.next();
String str=(String)o;
if ("NBA".equals(str)){
listIterator.add("Java");
}
}
System.out.println(list);
}
}
练习:删除集合中重复的元素
public class lianxi {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(100);
list.add(100);
list.add(200);
list.add(100);
list.add(400);
list.add(100);
list.add(500);
list.add(100);
list.add(400);
list.add(100);
list.add(500);
// for (int i = 0; i < list.size(); i++) {
// for (int j = i+1; j < list.size()-1; j++) {
// Object o = list.get(i);
// Object o1 = list.get(j);
// if (o.equals(o1)){
// list.remove(o1);//按照元素删
// j=i;
// }
// }
// }
// System.out.println(list);
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size() - 1; j++) {
Object o = list.get(i);
Object o1 = list.get(j);
if (o.equals(o1)) {
list.remove(j);//按照索引删
j--;
}
}
}
System.out.println(list);
}
}
List实现类的区别
底层实现 | 优缺点 | 线程是否安全 | 效率 | 适用场景 | |
---|---|---|---|---|---|
ArrayList | 数组 | 查询容易,增删难 | 否 | 高 | 单线程,多查询,少增删的程序 |
Vector | 数组 | 查询容易,增删难 | 是 | 低 | 多线程,多查询,少增删的程序 |
LinkdeList | 链表 | 查询难,增删易 | 否 | 高 | 单线程,多增删,少查询的程序 |
泛型
泛型,是把类型明确工作,推迟到,创建对象,或调用方法时,再去明确的一种机制
泛型可以提高我们代码的灵活型,扩展性,可以把问题提前到编译期
public class lianxi {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
list.add(400);
list.add(500);
list.add(600);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){//不用去转型
System.out.println(iterator.next());
}
}
定义一个泛型类
public class MyTest<T, M> {
private T t;
private M m;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
}
public class MyTest2 {
public static void main(String[] args) {
MyTest<String, Integer> myTest = new MyTest<>();
myTest.setM(100);
myTest.setT("ABC");
Integer m = myTest.getM();
String t = myTest.getT();
}
}
定义一个泛型接口
public interface MyInterface<M> {
void test(M m);
}
class Test implements MyInterface<String>{
@Override
public void test(String s) {
System.out.println(s);
}
}
-
A:泛型通配符<?>: 任意类型,如果没有明确,那么就是Object以及任意的Java类了 B:? extends E: 向下限定,E及其子类 C:? super E: 向上限定,E及其父类 D:案例演示: 泛型高级之通配符的基本使用 /** - 泛型如果明确了数据类型以后,那么要求左右两边的数据类型必须一致 */ Collection<Object> col1 = new ArrayList<Object>() ; Collection<Object> col2 = new ArrayList<Animal>() ;//报错
// ? 表示任意的数据类型
Collection<?> col5 = new ArrayList() ;
Collection<?> col6 = new ArrayList() ;// ? extends E : 向下限定 , ? 表示的是E或者E的子类
可变参数的概述和使用
可变参数概述: 定义方法的时候不知道该定义多少个参数
格式: 修饰符 返回值类型 方法名(数据类型… 变量名){}
注意事项:这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
public class lianxi {
public static void main(String[] args) {
int sum=add(1,2,3,4,5);
int sum1=add(1,2,3);
System.out.println(sum);
System.out.println(sum1);
}
private static int add(double num,int...a) {
int sum=0;
for (int i:a){
sum+=i;
}
return sum;
}
}
Arrays工具类的asList()方法的使用
public class lianxi {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(100, 200, 300, 400, 500);
int[] arr={1,2,3};
Integer[] integers={1,2,3,4};
Integer[]integers1={1,2,3,4};
Integer[] integers2={1,2,3,4};
List<int[]> ints1 = Arrays.asList(arr);
System.out.println(ints1);
List<int[]> ints = Arrays.asList(arr, new int[]{10}, new int[]{1, 2, 34});//当我们使用 Arrays.asList()这个方法来转换集合的时候,如果我们传入一个或多个int[] 数组的时候,集合里面放的是数组的引用
System.out.println(ints);
List<Integer> list1 = Arrays.asList(integers);//当我们使用 Arrays.asList()这个方法来转换集合的时候,如果我们传入一个Integer[] 数组,那么他会把数组的元素取出来放到集合中
System.out.println(list1);
List<Integer[]> list2 = Arrays.asList(integers, integers1, integers2);//当我们使用 Arrays.asList()这个方法来转换集合的时候,如果我们传入多个Integer[] 数组的时候,集合放的是每个Integer[] 数组的引用
System.out.println(list2);
}
输出结果:
[[I@1540e19d]
[[I@1540e19d, [I@677327b6, [I@14ae5a5]
[1, 2, 3, 4]
[[Ljava.lang.Integer;@7f31245a, [Ljava.lang.Integer;@6d6f6e28, [Ljava.lang.Integer;@135fbaa4]
注意事项: 得到的集合长度是不可变的 你不能往这个转换后的集合中 添加元素(add) 和 删除元素
集合嵌套之ArrayList嵌套ArrayList
public class lianxi {
public static void main(String[] args) {
ArrayList<Student> nbalist= new ArrayList<>();
nbalist.add(new Student("杜兰特",25));
nbalist.add(new Student("詹姆斯",30));
nbalist.add(new Student("库里",26));
ArrayList<Student> cbalist = new ArrayList<>();
cbalist.add(new Student("易建联",29));
cbalist.add(new Student("郭艾伦",28));
cbalist.add(new Student("周琦",27));
ArrayList<Student> footballlist = new ArrayList<>();
footballlist.add(new Student("贝克汉姆",20));
footballlist.add(new Student("C罗",20));
footballlist.add(new Student("梅西",27));
ArrayList<ArrayList<Student>> objects = new ArrayList<>();
objects.add(nbalist);
objects.add(cbalist);
objects.add(footballlist);
for (int i = 0; i < objects.size(); i++) {
ArrayList<Student> students = objects.get(i);
for (int j = 0; j < students.size(); j++) {
Student student = students.get(j);
System.out.println(student.getName()+"=="+student.getAge());
}
}
for (ArrayList<Student>students:objects){
for (Student student:students){
System.out.println(student.getName()+"=="+student.getAge());
}
}
}
}