JavaSE学习笔记16:集合(二)

最爱琴女E 2020-11-08 16:58:52
学习 JAVASE 集合 笔记


集合(二)

关于集合元素的remove

迭代过程中,不能直接通过集合删除元素,要通过迭代器删除元素

package se3.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest06 {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(1);
c.add(2);
c.add(3);
Iterator it = c.iterator();
while (it.hasNext()){
//编写代码时next()方法返回值类型必须是Object
Object obj = it.next();
//c2.remove();//直接通过集合去删除元素,没有通知迭代器,会报错
//使用迭代器来删除
it.remove();//删除的一定是迭代器指向的当前元素
System.out.println(obj);
}
System.out.println(c.size());//0
}
}

List接口特有方法

测试List接口中常用方法
  1. List集合存储元素特点:有序可重复

    有序:List集合中的元素有下标,从0开始,以1递增

    可重复:存储一个1,还可以在存储1

  2. List既然是Collection接口的子接口,那么肯定List接口有自己“特色”的方法:

    以下只列出List接口常用的方法

    ​ void add(int index,Object element)

    ​ Object get(int index)

    ​ int indexOf(Object o)

    ​ int lastIndexOf(Object o)

    ​ Object remove(int index)

    ​ Object set(int index,Object element)

package se3.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class ListTest01 {
public static void main(String[] args) {
//创建List类型的集合
List myList = new ArrayList();
//List myList = new LinkedList();
//添加元素
myList.add("A");//默认都是向集合末尾添加元素
myList.add("B");
myList.add("C");
myList.add("C");
myList.add("D");
//在指定位置添加指定元素(第一个参数是下标)
//使用不多,对ArrayList来说效率比较低
myList.add(1,"KING");
//迭代
Iterator it = myList.iterator();
while (it.hasNext()){
Object obj = it.next();
System.out.print(obj + " ");
}
//运行结果:A KING B C D
System.out.println();
//根据下标获取元素
Object obj1 = myList.get(0);
System.out.println(obj1);//A
//因为有下标,所以list集合有自己比较特殊的遍历方式
//通过下标遍历(List集合特有的方式,Set没有)
for (int i = 0; i < myList.size(); i++) {
Object object = myList.get(i);
System.out.print(object + " ");
}//运行结果:A KING B C D
System.out.println();
//获取指定对象第一次出现处的索引
System.out.println(myList.indexOf("KING"));//1
//获取指定对象最后一次出现处的索引
System.out.println(myList.lastIndexOf("C"));//4
//删除指定下标的元素
//删除下标为0的元素
myList.remove(0);
System.out.println(myList.size());//5
//修改指定位置的元素
myList.set(2,"Soft");
//遍历
for (int i = 0; i < myList.size(); i++) {
Object object = myList.get(i);
System.out.print(object + " ");
}
//运行结果:KING B Soft C D
}
}

ArrayList集合

ArrayList集合初始化容量及扩容
1. 默认初始化容量是10(底层先创建长度为0的数组,当添加第一个元素的时候,初始化容量为10)
2. 集合底层是一个Object[]数组
3. ArrayList集合的扩容
原容量的1.5倍
ArrayList集合底层是数组,怎么优化?
尽可能少的扩容,因为数组扩容效率低,建议使用ArrayList集合的时候预估计元素的个数,给定一个初始化容量。
4. 数组优点:检索效率高
5. 数组缺点:随机增删元素效率较低,以及数组无法存储大数据量(很难找到一块大的连续的存储空间)
6. 向数组末尾添加元素,效率很高,不受影响
7. 面试:这么多集合中,你用哪个集合最多?
答:ArrayList集合,因为往数组末尾添加元素效率不受影响,另外,我们检索/查找某个元素的操作比较多。
8.ArrayList集合是非线程安全的
package se3.list;
import java.util.ArrayList;
import java.util.List;
public class ArrayListTest01 {
public static void main(String[] args) {
//默认初始化容量是10
List list1 = new ArrayList<>();
System.out.println(list1.size());//0
//指定初始化容量:20(数组长度是20)
List list2 = new ArrayList(20);
//集合的size()方法是获取当前集合中元素的个数,不是获取集合的容量
System.out.println(list2.size());//0
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6);
list1.add(7);
list1.add(8);
list1.add(9);
list1.add(10);
System.out.println(list1.size());
//再加一个元素
list1.add(11);
//这里容量扩大为原来的1.5倍(自动扩容)
System.out.println(list1.size());//11
}
}
构造方法
  1. new ArrayList();
  2. new ArrayList(20);
package se3.list;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
//集合ArrayList的构造方法
public class ArrayListTest02 {
public static void main(String[] args) {
//默认初始化容量10
List myList1 = new ArrayList();
//指定初始化容量100
List myList2 = new ArrayList(100);
//创建一个HashSet集合
Collection c = new HashSet();
//添加元素到Set集合
c.add(100);
c.add(200);
c.add(900);
c.add(50);
//通过这个构造方法就可以将HashSet集合转换成List集合
List myList3 = new ArrayList(c);
for (int i = 0; i < myList3.size(); i++) {
System.out.println(myList3.get(i));
}
/*运行结果:
50
100
900
200
*/
}
}

单向链表数据结构

对于链表数据结构来说:基本的单元是节点Node

对于单向链表来说,任何一个节点Node中都有两个属性:

  1. 存储的数据
  2. 下一节点的内存地址
单向链表示意图

增加元素图

删除元素图

链表的优点与缺点
  1. 优点:随机增删元素效率较高。(因为增删元素不涉及到大量元素位移)。如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedList。
  2. 缺点:查询效率较低,每一次查找某个元素的时候都需要从头节点开始往下遍历。

ArrayList:把检索发挥到极致

LinkedList:把随机增删发挥到极致

package se3.list;
import java.util.LinkedList;
import java.util.List;
public class LinkedListTest01 {
public static void main(String[] args) {
/**
* LinkedList集合底层也是有下标的
* 注意:ArrayList之所以检索效率比较高,不是单纯因为下标的原因。是因为底层数组发挥的作用。
* LinkedList集合照样有下标,但是检索/查找某个元素的时候效率比较低,因为只能从头节点一个一个遍历。
*/
List list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
System.out.print(obj + " ");
}
//输出结果:a b c
}
}

双向链表与LinkedList集合

双向链表的基本单元还是节点Node

双向链表结构图

package se3.list;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LinkedListTest01 {
public static void main(String[] args) {
/**
* LinkedList集合底层也是有下标的
* 注意:ArrayList之所以检索效率比较高,不是单纯因为下标的原因。是因为底层数组发挥的作用。
* LinkedList集合照样有下标,但是检索/查找某个元素的时候效率比较低,因为只能从头节点一个一个遍历。
*/
List list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
System.out.print(obj + " ");
}
//输出结果:a b c
/**
* LinkedList集合有初始化容量吗?没有
* 不管是LinkedList还是ArrayList,以后不需要关心具体是哪个集合
* 因为我们要面向接口编程,调用的方法都是接口中的方法
*/
System.out.println();
List list2 = new ArrayList();//这样写表示底层用了数组
//List list2 = new LinkedList();//这样写表示底层用了双向链表
list2.add("123");
list2.add("456");
list2.add("789");
for (int i = 0; i < list2.size(); i++) {
System.out.print(list2.get(i) + " ");
}
//输出结果:123 456 789
}
}

Vector集合

package se3.list;
import java.util.*;
/**Vector
* 1.底层也是一个数组
* 2.初始化容量:10
* 3.怎么扩容的?
* Vector集合扩容的特点:10-->20-->40-->80
*扩容之后是原容量的2倍
* 4.ArrayList集合扩容特点:10-->15-->15*1.5
* ArrayList扩容是原容量的1.5倍
* 5.Vector中所有的方法都是线程同步的,都带有synchronized关键字
* 是线程安全的。效率比较低,使用较少了。
*/
public class VectorTest {
public static void main(String[] args) {
//创建一个集合
List v = new Vector();
//Vector v = new Vector();
//默认容量10
v.add(1);
v.add(2);
v.add(3);
v.add(4);
v.add(5);
v.add(6);
v.add(7);
v.add(8);
v.add(9);
v.add(10);
//满了之后扩容(扩容之后是20)
v.add(11);
Iterator it = v.iterator();
while (it.hasNext()){
Object object = it.next();
System.out.print(object + " ");
}//输出结果;1 2 3 4 5 6 7 8 9 10 11
/*
怎么将一个线程不安全的ArrayList集合转换成线程安全的呢?
使用集合工具类:java.util.Collections;
java.util.Collection是集合接口
java.util.Collections是集合工具类
*/
List mylist = new ArrayList();//非线程安全的
//变成线程安全的
Collections.synchronizedList(mylist);
//myList集合就是线程安全的了
mylist.add("111");
mylist.add("222");
mylist.add("333");
}
}

泛型

泛型这种语法机制,只在程序编译阶段起作用,只是给编译器看的。(运行阶段泛型没用)

使用泛型的优点:
  1. 集合中存储的元素类型统一了
  2. 从集合中取出的元素类型是泛型指定的类型,不需要进行大量的向下转型
缺点

泛型的缺点:导致集合中存储的元素缺乏多样性!

注意:大多数业务中,集合的元素类型还是统一的。

package se3.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest01 {
public static void main(String[] args) {
//不使用泛型机制,分析程序存在的缺点
List myList = new ArrayList();
//准备对象
Cat c = new Cat();
Bird b = new Bird();
//将对象添加到集合当中
myList.add(c);
myList.add(b);
//遍历集合,取出Cat让她抓老鼠,取出Bird让她飞!
Iterator it = myList.iterator();
while (it.hasNext()){
Object obj = it.next();
//强制转型
if (obj instanceof Animal){
Animal a = (Animal)obj;
a.move();
}
if(obj instanceof Cat){
Cat c1 = (Cat)obj;
c1.catMouse();
}
if(obj instanceof Bird){
Bird b1 = (Bird)obj;
b1.fly();
}
}
//输出结果:
//动物在移动!
//猫在抓老鼠!
//动物在移动!
//鸟儿在飞翔!
}
}
class Animal{
//父类自带的方法
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
//特有方法
public void catMouse(){
System.out.println("猫在抓老鼠!");
}
}
class Bird extends Animal{
//特有方法
public void fly(){
System.out.println("鸟儿在飞翔!");
}
}
package se3.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest02 {
public static void main(String[] args) {
//使用泛型List<Animal2>之后,表示List集合中只允许存储Animal类型的数据
//用泛型来指定集合中数据存储的数据类型
List<Animal2> myList2 = new ArrayList<Animal2>();
//指定list集合在只能存储Animal
//myList2.add("abc");报错
Cat2 c2 = new Cat2();
Bird2 b2 = new Bird2();
myList2.add(c2);
myList2.add(b2);
//获取迭代器
//这个表示迭代器迭代的是Animal类型
Iterator<Animal2> it2 = myList2.iterator();
while (it2.hasNext()){
//使用泛型之后,每一次迭代返回的数据类型都是Animal类型
Animal2 a2 = it2.next();
//如果直接使用Animal类型,不需要进行强制类型转换了,直接调用
//a2.move();
if(a2 instanceof Cat2){
Cat2 x = (Cat2)a2;
x.catMouse();
}
if (a2 instanceof Bird2){
Bird2 y = (Bird2)a2;
y.fly();
}
}
//输出结果:
//猫在抓老鼠!
//鸟儿在飞翔!
}
}
class Animal2{
//父类自带的方法
public void move(){
System.out.println("动物在移动!");
}
}
class Cat2 extends Animal2{
//特有方法
public void catMouse(){
System.out.println("猫在抓老鼠!");
}
}
class Bird2 extends Animal2{
//特有方法
public void fly(){
System.out.println("鸟儿在飞翔!");
}
}
自动类型推断

JDK8之后引入了:自动类型推断机制(又称钻石表达式)

package se3.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest03 {
public static void main(String[] args) {
//ArrayList<这里的类型会自动推断,前提是JDK8之后才允许>
//自动类型推断
//List<Animal2> myList3 = new ArrayList<Animal2>();
List<Animal2> myList3 = new ArrayList<>();
myList3.add(new Animal2());
myList3.add(new Cat2());
myList3.add(new Bird2());
//遍历
Iterator<Animal2> it3 = myList3.iterator();
while (it3.hasNext()){
Animal2 aa = it3.next();
aa.move();
}
List<String> stringList = new ArrayList<>();
//类型不匹配
//stringList.add(new Cat2());
//stringList.add(123);
stringList.add("http://www.163.com");
stringList.add("http://www.baidu.com");
stringList.add("http://www.bjpownode.com");
Iterator<String> its = stringList.iterator();
while (its.hasNext()){
String s = its.next();
String newString = s.substring(7);
System.out.println(newString);
}
/**
* 运行结果:
* 动物在移动!
* 动物在移动!
* 动物在移动!
* www.163.com
* www.baidu.com
* www.bjpownode.com
*/
}
}
自定义泛型

自定义泛型的时候,<>(尖括号)中的是一个标识符,随便写

java源码中经常出现的是
1.E是Element单词首字母
2.T是Type单词首字母

package se3.collection;
public class GenericTest04<标识符随便写> {
public void doSome(标识符随便写 o){
System.out.println(o);
}
public static void main(String[] args) {
GenericTest04<String> gt = new GenericTest04<>();
//gt.doSome(100);报错:类型不匹配
gt.doSome("qwq");//输出qwq
//==========================================
GenericTest04<Integer> gt2 = new GenericTest04<>();
//gt2.doSome("阿波");报错:类型不匹配
gt2.doSome(100);//输出100
MyIterator<String> mi = new MyIterator<>();
String s1 = mi.get();
//Animal aaa2 = mi2.get();报错
MyIterator<Animal> mi2 = new MyIterator<>();
Animal aaa = mi2.get();
//String s2 = mi2.get();报错
//不用泛型就是Object类型
GenericTest04 gt3 = new GenericTest04();
gt3.doSome(new Object());
gt3.doSome(200);
gt3.doSome("阿波");
}
}
class MyIterator<T>{
public T get(){
return null;
}
}

集合使用foreach

package se3.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ForEachTest01 {
public static void main(String[] args) {
//创建List集合
List<String> stringList = new ArrayList<>();
//添加元素
stringList.add("hello");
stringList.add("阿波");
stringList.add("123");
//遍历,使用迭代器方式
Iterator<String> it = stringList.iterator();
while (it.hasNext()){
String s = it.next();
System.out.print(s + " ");
}
System.out.println();
//使用下标的方式(只针对于有下标的集合)
for (int i = 0; i < stringList.size(); i++) {
System.out.print(stringList.get(i) + " ");
}
System.out.println();
//使用foreach
for (String s : stringList) {//因为泛型使用的是Sting类型,所以是String s
System.out.print(s + " ");
}
System.out.println();
List<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
for (Integer i : list){//i代表集合中的元素
System.out.print(i + " ");
}
/**
* 输出结果:
* hello 阿波 123
* hello 阿波 123
* hello 阿波 123
* 100 200 300
*/
}
}
版权声明
本文为[最爱琴女E]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/Sona-36D/p/13944786.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云