0
点赞
收藏
分享

微信扫一扫

Java学习记录 Day14(List集合、泛型、for-each、可变参数)


文章目录

  • ​​Day 14​​
  • ​​集合​​
  • ​​集合框架的并发异常​​
  • ​​函数式接口​​
  • ​​泛型​​
  • ​​for-each循环​​
  • ​​可变参数​​
  • ​​ArrayList嵌套​​

Day 14

2019年5月3日。
这是我学习Java的第十四天。
这一天,我学到了以下的知识。

集合

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类

集合和数组的区别有

  1. 长度区别:
    数组的长度是固定的而集合的长度是可变的
  2. 存储数据类型的区别:
    数组可以存储基本数据类型 , 也可以存储引用数据类型; 而集合只能存储引用数据类型
  3. 内容区别:
    数组只能存储同种数据类型的元素 ,集合可以存储不同类型的元素

在集合框架中,Collection是顶层父接口,List和Set为子接口,List的实现类又有ArrayList、LinkedList、Vector,而Set的实现类有HashSet、LinkedHashSet、TreeSet,集合框架图如下所示

Java学习记录 Day14(List集合、泛型、for-each、可变参数)_Java


首先,讲解Collection顶层父接口下的方法

  • Collection
    常用的成员方法
  • 添加功能
  • ​boolean add(Object obj)​​:添加一个元素
  • ​boolean addAll(Collection c)​​:添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
  • 删除功能
  • ​void clear()​​:移除所有元素
  • ​boolean remove(Object o)​​:移除一个元素
  • ​boolean removeAll(Collection c)​​:移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素,如果没有交集元素 则删除失败 返回false
  • 判断功能
  • ​boolean contains(Object o)​​:判断集合中是否包含指定的元素
  • ​boolean containsAll(Collection c)​​:判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
  • ​boolean isEmpty()​​:判断集合是否为空
  • 获取功能
  • ​Iterator<E> iterator()​​:获取一个迭代器(主要用于遍历集合)
    -​​​iterator().next()​​:让迭代器的指针下移
    -​​​iterator().hasNext()​​:判断迭代器的指针下面是否为空
  • 长度功能
  • ​int size()​​:元素的个数
  • 交集功能
  • ​boolean retainAll(Collection c)​​:获取两个集合的交集元素(交集:两个集合都有的元素)
  • 转换功能
  • ​Object[] toArray()​​:将集合转换为数组(依次获取集合中的每一个元素)

其次,讲解List子接口下的方法

  • List
    List,特点为元素有序,并且每一个元素都存在一个索引,元素可以重复
    常用的特有方法
  • ​void add(int index,E element)​​:在指定索引处添加元素
  • ​E remove(int index)​​:移除指定索引处的元素 ,返回的是移除的元素
  • ​E get(int index)​​:获取指定索引处的元素
  • ​E set(int index,E element)​​:更改指定索引处的元素 返回的而是被替换的元素
  • ​ListIterator<E> listIterator()​​:获取一个list迭代器
    -​​​boolean hasPrevious()​​:是否存在前一个元素
    -​​​E previous():​​:返回列表中的前一个元素
    - 注意: 通过以上两个方法,可以实现反向遍历 但是注意,要在成反向遍历之前,要先进行正向遍历 ,这样迭代器的指针才能移到最后。如果直接反向遍历是没有效果的 ,因为指针默认位置就在最前面,它前面没有元素

最后,讲解List接口下的实现类(Set接口和Set接口下的实现类暂时不讲解)

  • ArrayList
    底层数据结构是数组,查询快,增删慢。
    线程不安全,效率高。
  • LinkedList
    底层数据结构是链表,查询慢,增删快。
    线程不安全,效率高。
  • Vector
    底层数据结构是数组,查询快,增删慢。
    线程安全,效率低。

集合框架的并发异常

当我们用Iterator这个迭代器遍历采用hasNext方法和next方法,用集合去修改集合,就会出现并发修改异常(ConcurrentModificationException)
原因是我们的迭代依赖与集合,当我们往集合中添加好了元素之后,获取迭代器 ,那么迭代器已经知道了集合的元素个数,这个时候你在遍历的时候又突然想给集合里面加一个元素(用的是集合的add方法),那迭代器不同意,就报错了
解决方案如下

  • 用ListIterator迭代器遍历,并且用迭代器自带的add方法添加元素,那就不会报错了,步骤如下
    - 迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)
    - 集合遍历元素,集合修改元素
  • 使用for循环遍历集合,添加元素,不会报错

函数式接口

JDK1.8之后引入的一种机制,若接口中只有一个抽象方法,那么就可以使用Lanbda表达式来简写匿名内部类

代码如下

public class MyTest3 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(100);
list.add(200);
list.add(100);

//Consumer con= new Consumer() {
// @Override
// public void accept(Object o) {
// System.out.println(o);
// }
// };
//函数式接口:接口中只有一个抽象方法,那么你就可以使用 Lambda 表达式来简写匿名内部类
Consumer con = (obj) -> System.out.println(obj);

Consumer con2 = System.out::println;
//JDK1.8 对应函数式接口,可以使用Lambda 表达式来简写
//list.forEach(con2);
list.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});

}
}

泛型

JDK1.5之后引入的一种机制,是把类型明确工作推迟到创建对象或调用方法时,再去明确的一种机制,泛型可以提高代码的灵活性,扩展性,把问题提前到编译器
格式:​​<数据类型> 这里的数据类型只能是引用数据类型​优点

  1. 把运行时期的问题提前到了编译期间(泛型只在编译期有效 ,但在运行期就擦除了)
  2. 避免了强制类型转换
  3. 优化了程序设计,解决了黄色警告线

使用


  • - 概述:把泛型定义在方法上
    - 格式:​​public <泛型类型> 返回类型 方法名(泛型类型 变量名​​ - 定义

public class Phone {

/**
* 泛型方法
*/
public <E> void show(E e){
System.out.println(e);
}

  • 接口
    - 概述:把泛型定义在接口上
    - 格式:​​public interface 接口名<泛型类型>​​ - 定义

//一般定义
public interface Inter<T> {

public abstract void show(T t) ;
}
——————————————————————————————————————
//特殊定义一: 在定义子类的时候,已经可以明确数据类型了
//public class InterImpl implements Inter<String> {
//
// @Override
// public void show(String t) {
// System.out.println(t);
// }
//
//}
——————————————————————————————————————
//特殊定义二: 在定义子类的时候,还不知道到底使用什么数据类型,这个时候就需要将这个子类也定义成泛型
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}

通配符

  • ​泛型通配符<?>​​:任意类型,如果没有明确,那么就是Object以及任意的Java类了
  • ​? extends E​​:向下限定,?表示的是E及其子类
  • ​? super E​​:向上限定,?表示的是E及其父类

for-each循环

JDK1.5之后引入的一种机制,是简化数组和Collection集合的遍历
格式

for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}

使用步骤

  1. 先确定容器中的元素的数据类型
  2. 确定容器的名字
  3. 注意:使用新式for循环在遍历时,若想在集合中添加或删除元素,同样会报出并发修改异常的错误(解决方案如上)

可变参数

若在定义方法的时候不知道该定义多少个参数,就可以使用可变参数
格式:​​修饰符 返回值类型 方法名(数据类型… 变量名){}​

注意事项

  1. 这里的变量其实是一个数组
  2. 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

范例

public static int add(int... a){

// 定义一个累加变量
int sum = 0 ;

for(int s : a ){
sum += s ;
}

return sum;
}

特殊
在集合中,存在一个与可变参数产生联动的方法:​​​public static <T> List<T> asList(T... a)​​ 该方法可以把多个数组转换成集合,但需要注意的是:

  • 若传入一个或多个int[]数组,则集合里面存放的是数组的引用
  • 若传入一个或多个Integer[]数组,则会把数组的元素取出来并放到集合中
  • 若通过这个方法获取到了一个转换过来的集合,则这个集合的长度是固定的,即只能从集合中取出元素,而不能增删元素

ArrayList嵌套

类似于数组的遍历,集合也有相似的遍历方式(即用两层for循环进行遍历)

代码如下

public class MyTest {
public static void main(String[] args) {
//A:
//需求:
//我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生。ArrayList<Student>
//但是呢,我们旁边是不是还有班级,每个班级是不是也是一个ArrayList<Student>。
//而我现在有多个ArrayList<Student>。也要用集合存储,怎么办呢 ?
//集合嵌套之ArrayList嵌套ArrayList

ArrayList<Student> javaList = new ArrayList<>();
javaList.add(new Student("张三1", 23));
javaList.add(new Student("张三2", 23));
javaList.add(new Student("张三3", 23));

ArrayList<Student> webList = new ArrayList<>();
webList.add(new Student("张三4", 23));
webList.add(new Student("张三5", 23));
webList.add(new Student("张三6", 23));

ArrayList<Student> linuxList = new ArrayList<>();
linuxList.add(new Student("张三7", 23));
linuxList.add(new Student("张三8", 23));
linuxList.add(new Student("张三9", 23));

//创建一个大的集合,大的集合放小的集合
ArrayList<ArrayList<Student>> maxList = new ArrayList<>();
maxList.add(javaList);
maxList.add(webList);
maxList.add(linuxList);

//
//遍历:普通for循环
for (int i = 0; i < maxList.size(); i++) {
ArrayList<Student> minList = maxList.get(i);
for (int j = 0; j < minList.size(); j++) {
Student student = minList.get(j);
System.out.println(student.getName() + "===" + student.getAge());
}

}
System.out.println("----------------------------------------------------------");
//新式for循环遍历
for (ArrayList<Student> students : maxList) {
for (Student student : students) {
System.out.println(student.getName() + "===" + student.getAge());
}
}
}
}


举报

相关推荐

0 条评论