华杉研发九学习日记18
一,集合框架
1.1 集合和数组的区别
集合就是在java中用来保存多个对象的容器
集合是数组的升级版,集合中只能放置对象[object].
数组: 在java中用来保存多个具有相同数据类型数据的容器
数组弊端:
- 1.数组只能保存相同的数据类型的数据
- 2.数组的长度一旦定义永不可变
数组可以保存所有的数据类型的数据 (基本数据和引用数据)
集合只能保存引用数据类型
集合的优势:
- 1.集合中可以保存多个不同数据类型的数据
- 2.集合的长度不定,可以随着数据增加而扩容
集合在后期的开发项目中,经常使用。
集合框架指的是java.util 包中定义的各种容器类、相关的工具类、接口的统称。不同的容器存储不同结构的数据。使用时要进行导包操作。
上图是集合框架的整个家族体系
点线框是接口,虚线框是抽象类,实线框是类
简图:
集合一共分为两大类(3小类):
Collection…即集合,它是像数组一样的单值容器,容器的容量可以动态变化(数组的容量是固定的) ----单列
- List…-…列表,可以简单理解为有序数组。
- set-…–集合,类似于数学中的集合,容器中不允许出现重复元素
- Map…-即映射(或字典) ,它是键值对容器,容量可以动态变化
二,Collection
Collection是单列集合的总的父接口,我们就不需要去直接操作接口,而是学习其方法即可.
三,List接口
List接口规定了有序集合应该具有什么功能。有序不是内容有序,而是存放顺序有序。既然有序,意味着有下标的概念
List集合是一个有序的,可以包含重复元素的集合。
List集合是接口,该接口中除了继承了Collection父接口中的所有的方法之外,也自己扩展自己独有的方法。
List是接口,不能用来创建对象,所用我们只需要学习其方法即可
四,ArrayList
4.1 方法
ArravList是List接口的实现子类,因为List接口继承了Collection接口,Collection接口继承了Iterable接口,因此ArrayList会实现List、Collection、Iterable中全部的方法
ArrayLlist之所以叫ArrayList,是因为ArrayList底层是靠数组来存放元素的。与我们之前所学数组不同的是,之前学习的数组长度不能改变,ArrayList是长度可变的数组,长度不足时会自动扩充容量
由于底层是靠数组完成的数据存取,所以查询效率高(根据index查询),增删效率低.(类似于顺序表)
数组增加或者删除元素时,需要移动元素,所以效率偏低
对单个数据:
// 创建一个List集合对象
// ArrayList list = new ArrayList(); // 10
List list =new ArrayList();
// 继承的Collection的方法
System.out.println(list.size()); // 0
System.out.println(list.isEmpty()); // true
list.add("小猫"); // 向上转型 -->Object
list.add("小咪");
list.add(123); // 自动装箱-->Integer 向上转型-->Object
list.add(123);
list.add(1,"小猫咪");
// get 获取
System.out.println(list);
Object o = list.get(1);
System.out.println(o);
// indexOf 获取下标
System.out.println(list.indexOf("小咪"));
System.out.println(list.lastIndexOf(123));
// remove 移除
list.remove(2);
// set 设置值
System.out.println(list);
list.set(3,"大猫咪");
System.out.println(list);
// subList 截取集合
List list2 =list.subList(0,2);
System.out.println(list2);
System.out.println(list.size()); // 3
System.out.println(list.isEmpty()); // false
System.out.println(list.contains("小猫")); //比对数据 true
list.remove("小猫"); // 移除数据
System.out.println(list.contains("小猫")); // false
list.clear(); // 清楚所有
System.out.println(list.size()); // 0
对批量数据:
List list1 = new ArrayList();
list1.add("小猫");
list1.add("小咪");
System.out.println(list1);
List list2 = new ArrayList();
list2.add("小猫咪");
list2.add("小狗");
System.out.println(list2);
// 在集合后面直接追加一个集合
list2.addAll(list1);
System.out.println(list2);
// 判断一个集合是否包含另一个集合全部
System.out.println(list2.containsAll(list1));
// 删除所有list1的元素
list2.removeAll(list1);
System.out.println(list2);
// 按照索引添加
list2.addAll(1,list1);
System.out.println(list2);
// 如果要移除数字类型的对象,需要用到包装类包装
// 否则视为移除数字对应的索引下标
list2.add(123);
list2.remove(new Integer(123));
4.2 遍历
- 普通for循环
- 加强for循环
- 迭代器
List list = new ArrayList();
list.add("小孤鸡");
list.add(111);
list.add(true);
// 遍历
// 方式一,普通for循环
for(int i=0;i<list.size();i++){
Object o = list.get(i);
System.out.println(o);
}
System.out.println("==============");
// 方式二,加强for循环
for(Object o:list){
System.out.println(o);
}
System.out.println("==============");
// 方式三,迭代器
Iterator it = list.iterator();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);
}
五,泛型
什么是泛型?
泛型就是广泛的数据类型,参数化类型,它的作用就是把变量或者属性或者方法的参数或者方法的返回值等的类型看做是一个参数。这样就可以写出来通用的代码,让代码更加简洁。在使用的时候,传入真正的类型。这个过
程类似于方法的形参和实参
为什么要用泛型?
1.优化代码,让代码更简洁更通用
例如: 拿打印数组来说,我们可以定义一个工具类ArrayTool,ArrayTool提供打印数组的方法
public class ArrayTool <T>{
// T : 泛型,当你创建对象时,来对该不定的类型定义其确定的类型,使于数据的传递
//如果创建财象时,设有定文其美型。则欢认类型为0bject
public void printArray(T arr[]) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
//定义方法,来实现传入数组,遍历数组把其数据的元素打印到控制台
// public static void printArray(int arr[]){
// for(int i=0; i<arr.length; i++){
// System.out.print(arr[i]+" ");
// }
// }
// public static void printArray(String arr[]){
// for(int i=0; i<arr.length; i++){
// System.out.print(arr[i]+" ");
// }
// }
public static void main(String[] args) {
// ArrayTool arrayTool = new ArrayTool();
// int arr[]={12,21,34,56,7};
// arrayTool.printArray(arr);
// String s[]={"小猫","小咪","小猫咪"};
// arrayTool.printArray(s);
ArrayTool<String> a = new ArrayTool<String>();
String s[]={"小猫","小咪","小猫咪"};
a.printArray(s);
//将参数类型也传递过去
ArrayTool<Integer> a1 = new ArrayTool<Integer>();
Integer arr[]={1,255,32,444,111};
a1.printArray(arr);
// 如果没有定义类型,则默认为Object
ArrayTool at3 = new ArrayTool();
at3.printArray(arr);
}
}
2.编写代码期间预报错误,防止运行期间出错,减少运行期间的类型转换
不使用泛型的时候,List中可以存放任意对象类型。会出现以下问题:
1.报了一堆警告
2.有可能取元素的时候,记错类型,进而产生转换类型的时候出现异常
3.取元素需要类型转换 (因为默认object类型)
在Java中,泛型有3种用法:泛型类,泛型方法,泛型接口。
泛型类:
所谓的泛型类,就是对类进行泛型的设定。对类设定泛型,这个泛型将作用于类的属性,类的方法,类的方法的返回值,类中的局部变量。
泛型类的语法格式:
在类名的后面加上<类型占位符>
通配符 ?
限定通配符的上界
<?extends类型>可以限制通配符的上界. 例如:<? extends Animal>意思是?可以是Animal,也可以是Animal的子类(或孙子,重孙等) **限定通配符的下界** <? super类型>可以限定通配符的下界. 例如:<? extends Cat>意思是?可以是Cat,也可以是Cat的父类(或爷爷,或爷爷的父类等) ## 六,LinkedList LinkedList是List接口的实现子类,该类中的集合也是有序的,可以包含重复元素的集合 LinkedList在底层是以双链表的形式保存数据,**查询速度慢,增删数据速度快。** LinkedList除了继承List,Collection中的所有的方法之外,自己也扩展了一部分方法 继承的方法::add()addAll() size() contains() containsAll) remove() clear() get() indexof()lastIndexOf( lterator() subList() isEmpty0 toCharArray0 自己的方法:**addFirst() addLast()** getFirst() getLast() element() offerFirst() offerLast() pollFirst()pollLast( push() removeFirst() removeLast() ```java // 这里向上转型成List,无法用到自己独有的方法 List list = new LinkedList<>(); list.add("张无忌"); list.add("赵敏"); list.add(1,"周芷若"); System.out.println(list); list.set(1,"赵敏"); System.out.println(list); list.remove("赵敏"); System.out.println(list); list.removeAll(list); System.out.println(list); System.out.println(list.isEmpty()); System.out.println("==================="); LinkedList link = new LinkedList<>(); link.add(1); link.add(2); link.add(3); link.add(4); System.out.println(link); link.addFirst(5); link.addLast(111); System.out.println(link); link.removeFirst(); link.removeLast(); System.out.println(link); // 也是加 offer link.offerFirst(99); link.offerLast(88); System.out.println(link); // 也是删 poll link.pollFirst(); link.pollLast(); System.out.println(link); ``` **ArrayList与LinkedList区别** **相同点** ArrayList和LinkedList都实现了List接口(及父接口),因此具有相同的功能。 **不同点** **ArrayList底层数据结构是数组。数组中的元素在物理上连续,逻辑上也连续**。因此ArrayList增、删比较费时。ArrayList在插入元素的时候,需要先将元素整体后移,再插入数据。插入的位置越靠前,移动的元素越多。ArrayList在删除元素的时候,需要将元素整体前移。删除的元素位置越靠前,移动的元素越多。但根据下标查找元素效率极高,因为数组在内存中是连续的存储空间,给出下标能快速定位到元素。