集合
1、集合
-
概念:对象的容器,实现类对对象常用的操作,类似数组功能。
-
和数组的区别:
-
数组长度固定,集合长度不固定。
-
数组可以存储基本类型和引用类型,集合只能存储引用类型。
-
-
位置:java.util*
2、collection父接口
-
注意事项:1.在迭代器中,不能连续调用it.next() 2.在迭代过程中不能使用collection.remove(),可以使用迭代器的删除,it.remove()
-
特点:代表一组任意类型的对象,无序、无下标、不能重复
-
迭代器迭代过程中,不能使用collection的删除方法,可以使用iterator(迭代器)的删除方法
-
方法:
-
public static void main(String[] args) { //创建集合 Collection collection = new ArrayList(); //添加元素 add collection.add("苹果"); collection.add("xigua"); collection.add(3306); collection.add('a'); //获取集合元素个数 collection.size System.out.println("删除前元素个数:"+collection.size()); //删除前元素个数:4 //遍历元素 //通过加强for进行便利 System.out.println("----------通过加强for进行便利-----------"); for (Object o:collection) { System.out.println(o); //苹果 xigua 3306 a } //通过迭代器遍历 iterator System.out.println("----------通过加强Iterator进行便利-----------"); Iterator iterator = collection.iterator(); while (iterator.hasNext()){ Object o = iterator.next(); System.out.println(o); //苹果 xigua 3306 a } //删除元素 remove iterator.remove collection.remove("苹果"); System.out.println("删除后元素个数:"+collection.size()); //删除后元素个数:3 //判断元素是否存在 collection.contains System.out.println(collection.contains("xigua")); //true //清除数据 collection.clear(); System.out.println(collection.size()); //0 }
-
3、List子接口
-
特点:有序(添加的顺序和便利的顺序一样)、有下标、元素可以重复
-
方法:
-
public static void main(String[] args) { List list = new ArrayList(); //添加元素 list.add("孙二"); list.add("张三"); list.add("李四"); //通过下标向集合添加元素 list.add(0,"赵大"); System.out.println(list.toString()); //[赵大, 孙二, 张三, 李四] //获取下标为2的元素 Object o = list.get(2); System.out.println(o); //张三 下标为2,第三个元素 //将下标为2的 张三 改为 王三 list.set(2,"王三"); System.out.println(list.get(2)); //王三 //遍历数组 //使用for循环遍历集合,因为List集合有下标 System.out.println("------使用for循环遍历集合,因为List集合有下标------"); for(int i = 0;i<list.size();i++){ System.out.print(list.get(i)+"\t"); //赵大 孙二 王三 李四 } System.out.println(); //使用增强for遍历List集合 System.out.println("-----使用增强for遍历List集合--------"); for (Object o1: list) { System.out.print(o1+"\t"); //赵大 孙二 王三 李四 } System.out.println(); //使用迭代器listiterator遍历集合 ListIterator iterator = list.listIterator(); //顺序遍历数组 System.out.println("-------顺序遍历数组-------"); while (iterator.hasNext()){ System.out.print(iterator.nextIndex()+":"+iterator.next()); //0:赵大1:孙二2:王三3:李四 } System.out.println(); System.out.println("-------逆序遍历数组-------"); while (iterator.hasPrevious()){ System.out.print(iterator.previousIndex()+":"+iterator.previous()); //3:李四2:王三1:孙二0:赵大 } System.out.println(); //判断元素是否存在 System.out.println(list.contains("张三")); //false //判断集合是否为空 System.out.println(list.isEmpty()); //false list.add("小莲花"); list.add("小翠"); System.out.println(list.toString()); //[赵大, 孙二, 王三, 李四, 小莲花, 小翠] //subList获取一个子集合 含头不含尾 List list1 = list.subList(list.size()-2,list.size()); System.out.println(list1.toString()); //[小莲花, 小翠] }
-
ArrayList源码分析(查询快,增删慢,数组结构)
-
默认容量大小DEFAULT_CAPACITY:10
-
初始化调用无参构造ArrayList集合,数组长度是0
-
如果没有向集合中添加任何元素,默认容量是:0
-
添加第一个元素之后,数组容量扩容为10
-
存放元素的数组:elementData
-
size:实际元素个数
-
扩容原理:扩容为原来的1.5倍,原大小使用二进制表示,然后右移,最后相加
-
使用System.arraycopy实现复制方法,将原集合的数据拷贝到扩容后的集合
-
add() 添加元素
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1; }
ArrayList常用方法
-
ArrayList.remove(Object o),只会删除第一个遇到的相同元素,并且返回true
public static void main(String[] args) { Student s1 = new Student("小翠",15,"女"); Student s2 = new Student("小莲花",17,"女"); Student s3 = new Student("小月",19,"女"); Student s4 = new Student("厚本",29,"女"); ArrayList arrayList = new ArrayList(); //添加元素 arrayList.add(s4); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); System.out.println(arrayList.toString()); //[Student{name='厚本', age=29}, Student{name='小翠', age=15}, // Student{name='小莲花', age=17},Student{name='小月', age=19}] //删除元素 arrayList.remove(new Student("厚本",29,"女")); System.out.println(arrayList.toString()); //[Student{name='小翠', age=15}, Student{name='小莲花', age=17}, // Student{name='小月', age=19}] //查找位置 System.out.println(arrayList.indexOf(new Student("小翠",15,"女"))); //0 }
LinkedList集合方法
LinkedList linkedList = new LinkedList(); Student s1 = new Student("小翠",15,"女"); Student s2 = new Student("小莲花",17,"女"); Student s3 = new Student("小月",19,"女"); Student s4 = new Student("厚本",29,"女"); //添加元素 linkedList.add(s1); linkedList.add(s2); linkedList.addFirst(s3);//将元素添加到第一个 linkedList.add(s4); System.out.println(linkedList.toString()); //删除元素 linkedList.remove(s4); //使用equals System.out.println(linkedList.toString()); //迭代器遍历元素 System.out.println("--------迭代器遍历元素--------"); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next().toString()); } //列表迭代器 System.out.println("--------列表迭代器遍历元素--------"); ListIterator listIterator = linkedList.listIterator(); System.out.println(" -----列表迭代器先序遍历元素----"); while (listIterator.hasNext()){ System.out.println(listIterator.previousIndex()+":"+listIterator.next().toString()); } System.out.println(" -----列表迭代器后序遍历元素---- "); while (listIterator.hasPrevious()){ System.out.println(listIterator.previousIndex()+":"+listIterator.previous().toString()); } //判断 System.out.println(linkedList.contains(s1)); System.out.println(linkedList.isEmpty()); //查找位置 System.out.println(linkedList.indexOf(s1));
队列
** * 队列:先进先出,数据结构的一种 * Queue:队列的接口,LinkedList实现 * 核心操作 * 入队:offer() * 出队:poll() */ public class DemoQueue { public static void main(String[] args) { //创建队列 Queue queue = new LinkedList(); //入队(添加元素) queue.offer("北京1"); queue.offer("上海2"); queue.offer("深圳3"); System.out.println("元素个数:"+ queue.size()); //元素个数:3 System.out.println("直接打印:"+queue.toString()); //直接打印:[北京1, 上海2, 深圳3] //出队(删除元素) System.out.println("-----出队-----"); int size = queue.size(); for (int i =0;i<size;i++){ System.out.println(queue.poll()); //北京1 上海2 深圳3 } System.out.println("出队后的个数:"+queue.size()); //出队后的个数:0 } }
栈
/** * 栈:先进后出的一种数据结构 * 可以使用LinkedList代替,LinkedList也实现了栈结构 * Stack类:继承Vector * 出栈必须使用一个变量来获取栈的长度,因为出栈的过程中,栈的元素个数一直在减少 * 核心操作 * push();进栈 * pop();出栈 */ public class DemoStack { public static void main(String[] args) { //创建一个栈 Stack stack = new Stack(); //进栈 (添加元素) stack.push("北京1"); stack.push("上海2"); stack.push("深圳3"); System.out.println("元素个数:"+stack.size()); //元素个数:3 System.out.println("直接打印:"+stack.toString()); //直接打印:[北京1, 上海2, 深圳3] //出栈(删除元素) System.out.println("-----出栈-----"); int size = stack.size(); for(int i = 0;i<size;i++){ String s = (String)stack.pop(); System.out.println(s); //深圳3 上海2 北京1 } System.out.println("出栈之后的元素个数:"+stack.size()); //出栈之后的元素个数:0 } }
泛型
概念:
-
参数化类型、类型安全的集合,强制集合元素的类型必须一致
特点:
-
编译时即可检查,而非运行时抛出异常
-
访问时,不必类型转化(拆箱)
-
不同泛型之间引用不能相互赋值
优点
-
提高代码的重用性
-
防止类型转换异常,增加代码安全性
泛型的使用:泛型类
-
泛型类:在类名的后面添加<T,E,K,V.....>type,value,key,element
-
<T>表示类型占位符,代表一种引用类型。多个占位符之间使用逗号隔开
-
静态方法不能使用泛型,泛型只有在创建对象是才确定类型,静态方法通过类名.访问。
泛型方法:
-
在方法返回值的前面添加<T,....>
-
调用方法时确定类型
泛型接口:在接口名后面添加<T,....>
-
<T,...>表示类型占位符,代表一种引用类型。多个占位符之间使用逗号隔开
-
泛型接口不能创建泛型常量,常量必须进行赋值,创建接口时,才能确定泛型类型,
注意
-
泛型不能在类中声明静态属性
-
static修饰的属性是静态属性,先于对象,泛型类型取决于创建对象是传入的实际类型
-
-
泛型不能再类中初始化对象或者数组,但是可以声明引用或者数组
-
实例化对象需要分配空间,没有确定类型不能开辟空间
-
初始化数组时需要给元素进行分配空间,泛型类型不确定,无法分配空间
-
-
在类中不能使用泛型声明参数相同的个数重载
-
使用不同实际类型创建出的泛型类对象的引用不可以互相赋值
-
泛型的类型不能作为重载的依据
-
泛型的限制:
-
泛型上限:? extends Student ?代表Student类型或者Student类型的子类
-
泛型下限: ? supper Student ?代表Student类型或者Student类型的父类
-
public static void main(String[] args) { ArrayList<String> name = new ArrayList<>(); name.add("张三"); name.add("张si"); name.add("张wu"); show(name); ArrayList<Integer> num = new ArrayList<>(); num.add(100); num.add(200); num.add(300); show(num); } public static void show(ArrayList<?> list){ //? 表示任意类型 for(int i =0;i<list.size();i++){ System.out.println(list.get(i)); } }
-
-
Collections工具类
//创建集合 ArrayList<Integer> nums = new ArrayList<>(); nums.add(16); nums.add(17); nums.add(14); nums.add(11); nums.add(20); //sort排序 System.out.println("排序之前:"+nums.toString()); //排序之前:[16, 17, 14, 11, 20] Collections.sort(nums); System.out.println("排序之后:"+nums.toString()); //排序之后:[11, 14, 16, 17, 20] //二分查找 int pos = Collections.binarySearch(nums,20); if(pos>=0){ System.out.println("找到了"+pos); //找到了4 }else { System.out.println("没找到"); } //copy复制 ArrayList<Integer> dest = new ArrayList<>(); for(int i=0;i<nums.size();i++){ dest.add(0); } Collections.copy(dest,nums); System.out.println("dest:" + dest.toString()); //dest:[11, 14, 16, 17, 20] //reverse 反转 Collections.reverse(nums); System.out.println("反转之后:"+ nums); //反转之后:[20, 17, 16, 14, 11] //shuffle随机打乱 Collections.shuffle(nums); System.out.println("打乱之后:"+nums); //打乱之后:[16, 14, 20, 17, 11]
Set 接口
特点
-
无序(取出元素的顺序和存入的顺序不一样)、无下标、元素不可重复
方法
-
全部继承自Collection中的方法
public static void main(String[] args) { //创建集合 Set<String> set = new HashSet<>(); //添加元素 set.add("北京"); set.add("深圳"); set.add("北京"); set.add("上海"); set.add("北京"); System.out.println("元素个数:"+set.size()); System.out.println("直接打印:"+set.toString()); //删除 set.remove("北京"); //遍历 //3.1增强for for (String s:set) { System.out.println(s); } //3.2迭代器 Iterator iterator =set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } //判断是否存在和判断是否为空 System.out.println(set.contains("北京")); System.out.println(set.isEmpty());
HashSet
-
存储结构 :哈希表(数组+链表)
-
基于hashCode、equals实现元素不重复:当输入元素的哈希值相同时,会调用equals进行确认,结果为true,拒绝后者进入。
public static void main(String[] args) { //创建集合 HashSet<Student> hashSet = new HashSet<>(); Student s1 = new Student("张三",15,"男"); Student s2 = new Student("李四",15,"男"); Student s3 = new Student("王五",15,"男"); //添加元素 hashSet.add(s1); hashSet.add(s2); hashSet.add(s3); hashSet.add(new Student("王五",15,"男")); System.out.println("元素个数:"+hashSet.size()); System.out.println("直接打印:"+ hashSet.toString()); //删除 hashSet.remove(new Student("李四",15,"男")); System.out.println("删除之后元素个数:"+hashSet.size()); System.out.println("删除之后直接打印:"+ hashSet.toString()); //遍历 //3.1增强for for (Student s : hashSet) { System.out.println(s.toString()); } //3.2迭代器 Iterator<Student> iterator = hashSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } //判断 System.out.println(hashSet.contains(s1)); System.out.println(hashSet.isEmpty());
TreeSet
-
基于排序顺序实现元素不重复
-
实现了SortedSet接口,对集合元素自动排序
-
元素对象的类型必须实现Comparable接口,指定排序规则。
-
通过CompareTo方法确定是否为重复元素。左边比根小,右边比根小
-
需求:元素必须实现comparable接口,compareTo()返回零代表重复元素