一、自动装箱、拆箱;
- java中所有基本类型都有对应的封装类(引用数据类型)
- 我们学习的集合只能存放引用数据
1.1 数据类型转换
- 类型的容器;Java.lang
- 自动装箱:基本数据类型转为引用数据类型;
对应的封装类:int➡️Integer。int i = 1;自动装箱Integer i1 = i ; boolean : Boolean
double :Double ;float:Float ; char :Charater ;byte :Byte ; short : Short ;long:Long
- 自动拆箱:引用数据类型转为基本数据类型;
1.2 数据比较与内存表示
- 引用数据类型在定义过程左边声明变量在栈中,右边new在堆中,具体的基本数据类型存在方法区的常量池内。(注明:相同的的基本数据类型不会多次在常量池中开辟内容,常量池中的内容不会重复。)
- 指向问题
- 可以结合jvm内存的具体图来理解:例如a,a的变量名声明在栈中,new Integer()声明在堆中,100存储在方法区的产量池内。
- 由a在栈中指向堆中的new Integer()的地址,在由new Integer()指向100存储在方法区的产量池内的地址。
如果进行 == 比较:比较的是内存地址; a与c都是引用数据类型但是比较返回false,因为a变量内保存的是堆中的地址,c内保存的直接是常量池中100
对应的地址。
```java Integer a = new Integer(100); Integer b = new Integer(100);
Integer c = 100;
int d = 100;
3. 如图表示引用数据类型的内存存储。
![@_`N@~}VIRT4(Z]VK0S5}2R.png](https://cdn.nlark.com/yuque/0/2022/png/26800293/1649484151268-9c9629bc-ffc9-43f3-8c15-9b0a4371838d.png#clientId=u99f30391-3537-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=267&id=ud8f13676&margin=%5Bobject%20Object%5D&name=%40_%60N%40~%7DVIRT4%28Z%5DVK0S5%7D2R.png&originHeight=784&originWidth=1626&originalType=binary&ratio=1&rotation=0&showTitle=false&size=54154&status=done&style=none&taskId=u36df8df0-66cf-427f-afbc-beda58ca450&title=&width=552.7357788085938)
<a name="C3fcF"></a>
## 二、集合
1. 结构:Iterable最高 → Collection →(List )
1. 集合是容器,最能存放引用数据类型;
每个集合的实现类底层封装了一种数据结构;<br /> 每个集合都可以获取迭代器接口提供的迭代方法;
<a name="ZlCoQ"></a>
### 2.1 Collection接口
3. collection接口引用的子类对象,如果通过多态的方式添加数据,只能通过collection继承的迭代器来遍历出数据元素
3. Iterable仅有一个方法(遍历元素的迭代器)
```java
import com.eagleslab.pojo.User;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo01 {
public static void main(String[] args) {
//创建集合对象
Collection collection = new ArrayList();
Collection collection1 = collection;
//添加元素
collection.add(1000);//自动装箱
collection.add(true);//自动装箱
collection.add(new Object());
collection.add("hello world");
collection.add(new User());
//查看元素个数
System.out.println(collection.size());
//清空集合中的元素
//collection.clear();
//查看元素个数
System.out.println(collection.size());
//返回值指的是是否删除成功
boolean b = collection.remove("hello world");
System.out.println(collection.size());
System.out.println("是否删除成功 "+b);
//判断集合是否为空
boolean empty = collection.isEmpty();
System.out.println("集合是否为空 "+empty);
//判断集合中是否包含某一个元素
boolean contains = collection.contains("hello world");
boolean contains1 = collection.contains(1000);
System.out.println("是否包含 hello world "+contains);
System.out.println("是否包含 1000 "+contains1);
//比较集合对象是否相等
boolean equals = collection.equals(collection1);
//遍历集合的方法
Iterator iterator = collection.iterator();//获取集合的迭代器对象
/*
* iterator.hasNext() 判断集合中是否存在下一个元素 存在返回true 否则返回false
* iterator.next()指针往下走一个单元,并且将指向的元素返回
* */
while (iterator.hasNext()){
//指针往下走一个单元,并且将指向的元素返回
Object next = iterator.next();
System.out.println(next);
}
}
}
2.2、List接口(底层实现collection接口)
- 一个有序的集合,可以包含重复的元素;提供了按照索引访问元素的方(相较于collection);有序指存入和取出的顺序。
遍历方式:
可以用list.get(i)来遍历,list底层封装了数组,根据下标来取值。<br /> 也可以用,Iterator迭代器遍历
2.2.2 ArrayList
- 性能:底层数组,数组特性,查询效率高,增删效率低;
- 扩容机制:最初默认初始容量是10(10个元素),当数据超过10个就会触发扩容机制
- 扩容因子:(加载因子)是1.5
- 线程安全:否
2.2.3、LinkedList
- 定义:基于链表结构,操作方法于ArrarList基本一致;
- 性能:基于链表(查询效率低,随机增删效率高)的区别。
- 扩容机制:对容量没有要求;
2.2.4 Vector
- 性能:线程安全,集合的所有方法都增加了线程安全关键字,所以效率低,使用较少。
- 扩容机制:初试容量为0,扩容因子2.0。
2.2.5 Arraylist与vector的区别:
- 两个集合底层都封装了数据这一数据结构;
- arrarylist是线程不安全的,vector是线程安全的。所有的封装方法都相同。
- 扩容机制不同,arrarylist与vector最初默认初始容量都是10(10个元素),当数据超过10个就会触发扩容机制,Arrrylist扩容因子是1.5,vector扩容因子是2.0;
- arrarylist相对于vector每个方法多了一个线程同步的关键字
2.3、遍历方法
Iterator迭代器:iterator.hasNext()相当于一个指针,判断集合下一个单元是否含有元素返回true
如果有,就返回下一个数据存并指向下一个单元;
一但确定了迭代器,就不要改动集合数据,集合list去修改数据用迭代器去修改数据foreach遍历方式(JDK5之后出现的加强版for循环,不能代替for,不能下标来遍历)object是所有引用数据类型最大父类;for(数据类型 遍历的每一个元素:容器对象)
2.4【面试重点】
使用:String str1 = new String(“hello”); String str2 = “hello”;
User user1 = new User(年龄:20); User user2 = new User(年龄:20);
List list = new ArrayList();
List.add(str);
List.add(usr1);
List.contain(str2). 实际上是包含的;因为String底层重写了equals方法;而containList.contain(user2). 底层也是通过equals来比较的是比较内容的。因此可以得出包含结论,返回true。但是user类中并没有重写equals方法,因此在contain中来说是比较的是内存地址而不是内容故得出不包含返回false 重写equals有alt➕insert直接添加;
案例1:设计一个学生类只有当学生的相关信息,重写equals函数·全都相等才能相等
案例2:创建10个学生对象,存放于ArraryList集合,打印出年龄大于20岁的学生信息。
1、list.remove(删除元素);永远只能删除一个元素;(删除每个元素后就retun了)
2、List.contains方法底层代码四重写了equals方法,判断集合中是否包含类某一个元素,重写后比较的是内存,没有重写就是默认的是object类的equals方法,这时候比较的就是地址;
3、remove方法就是重写了equals方法,
2.5 集合的范型
(jdk1.5之后引入的新特性,强制让集合只能存放某一种数据类型)
- 结构 :钻石表达式<数据表达式>。 原本是默认数据类型——所有引用数据类型都能装
- ArrayList<数据类型> 名 = new ArrayList<>();后一个钻石表达式内省略;
创建集合对象:ArraryList<父类> 对象 = new ArraryList<>( );
对象.add(new 父类());<br /> 对象.add(new 子类());父类对子类对象的引用;
范型相当于一个数据类型,可以去继承也可指定父类,可以自定义。
- 为了固定一个类型,提高了安全性,不必担心类型转换错误,因为类型不按要求会报错。
Public class person< E>;
Private.E e;
Public void get(E e){}
三、Map接口
3.1 HashMap集合
存放键值对(key-value)的容器;
//创建集合对象
Map map = new HashMap();
//添加对象(键值对)
map.put(“name” ,”jack”);
(“key”,“value”).size()
// .containsvalue(“需要判断是否存在的值”)
// .equeals() //由key来获取value.get(“key”)
//把map集合中的key转为set集合;
Set set = map.keyset();
putAll一个集合的所有元素复制到另一个集合,
//删除或者查询都是通过key,根据key来删除整个键值map.remove(“key”)
value是key的一个替代品,我们在以后的操作时是根据key去操作的。map中key是不能重复的,value可以重复,如果添加的元素key重复,后添加的元素会覆盖前者
Map没有迭代器;先用keyset把key值全部给set对象,用set对象的迭代器来遍历;
map.entryset() 将map集合转为set集合:重要
entryset的范型是一个内部接口;
Set>entries = map名.entrySet
3.2 Hash散列/Hash桶:
数组和链表的结合体:想把数组和链表的有点都发挥出来。横向看是数组,纵向看是挂载着一些链表。
HashCode()方法会随机生成hash码值我们添加的元素是引用数据类型,那一定会继承object类的hashcode方法;
HashMap存储过程:
- 首先map集合会调用put方法来添加元素;
- 这时候,hashmap底层会生成hash值,根据这个hash值来计算该元素的位置(应该存放在数组的哪个索引(单元)下面);
- 确定了存放的单元,这时候就会拿着key的引用与该单元下所有的node
重写equals:
节点进行一个equals比较:
→ 当如进行equals比较时要看该引用数据类型有没有重写euqals方法(看比较的是内容还是地址)
→ 如果发现equals是true,那么新添加进来的节点把旧的节点覆盖掉; → 如果equals返回的是flase那么该节点就会存储在数组中的单向链表中 的最下面成为lastnode;
重写equals也一定要重写hsahcode方法否则并能实现按内容比较。
- 重写了hashcode方法后使得我们存储的引用数据类型只能存于同一存储单元下;
- 不重写就是存储位置不一定了;
3.3 HashSet集合:(底层封装hash散列,以及hashmap)
1、HashSet中不允许出现重复元素,不保证集合中的元素顺序。(无序、不重复)
2、允许出现null但是最多只能有一个null
3、添加数据时虽然重写的是add方法实际上调用的是put方法,
四、HashTable
- 区别:HashMap key-value可以为一次空注意多次key重复的覆盖问题; hashTable不能为空,因为他是线程安全的;
- 线程安全性:HashTable是线程同步的,也称线程安全;hashtabe是线程安全版的hashmap,其余所有操作都相同;和arrrylist与vectct一样,
- hashmap的执行效率要比hashtable高,因为hahstable 添加了线程安全同步字;在多线程的情况下执行效率不高,但是以后开发中可以通过别的途径来解决线程同步的问题;
五、treeMap集合
(底层封装了二叉树)可以根据存入数据的key的值来自动排序
如果你使用treeset或者terrmap时由于涉及比较,
故:如果使用引用数据类型一定要实现Comparable进行数据强转;
实现与重写Comparable接口:
- 整形或者字符串类型(在代码底层呢已经实现了Comparable接口重写了比较规则)的都可以进行排序;
- 参与比较的引用数据类型/实例必须重写实现底层的comparable接口,否则就会报错 ;
- 重写比较规则:由小到大的遍历,通过比较之后返回int类型的数据,小于0则返回左子树,大于0则返回右子树。返回正数负数还是0;
- 案例:使用hashmap统计一组字符数据中每个字母出现的次数;
步骤:先转为字符数组,在通过map,在entreyset,foreach遍历
matchs(“//w”)排除一些字符。 //W排除字符;//w排除非字符;/w排除下划线;
六、treeSet
添加数据的的本质与map相同;和hashmap与hashset的关系相同。
- 和treeMap一样,
- 无序不可重复,有覆盖,(可能不对)排序过程比较的是内容。
再hashSet中
- 自定义的引用数据类型默认情况下默认比较的是内存地址(双等号比较);
- 而非自定义的数据类型比较的是内容,因为重写了equals方法比较的是内容。
- —>所以要在自定义的数据类型,需要重写equals方法,让其输入对象时比较的是内容而不是内存地址。
七、Properties :
主要根据流对象用于读取配置文件:
- getProperties来读取配置文件;
- setproperties方法(String类型)用于存放string类型的键值对,根据key读取value
- 配置文件的类型就是properties;如jdbc ```java import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties;
public class PropertiesTest01 {
public static void main(String[] args) {
//创建流对象
FileReader fileReader = null;
try {
fileReader = new FileReader("db.properties");
//创建集合对象
Properties properties = new Properties();
properties.load(fileReader);
String url = properties.getProperty("db.url");
String driver = properties.getProperty("db.driver");
String username = properties.getProperty("db.username");
String password = properties.getProperty("db.password");
System.out.println(url);
System.out.println(driver);
System.out.println(username);
System.out.println(password);
} catch (IOException ioException) {
ioException.printStackTrace();
}finally {
//关闭流对象
try {
fileReader.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}
```
八、集合体系总结:
——>collection体系
——>List接口
——>ArrayList:底层数组,数组特性,查询效率高,增删效率低;
——>Vector:本身线程不安全的,默认初试容量是10,超过则触发扩 容机制,扩容因子是1.5
——>LinkedLIst:低层封装了单项链表结构,所以该集合有链表的所 有特性,查询效率不高,但是增删效率高,而且再linkerlist底
层封装了队列,可以调用入队出队方法。
---->Set接口<br /> ---->HashSet底层为我们集合了HashMap,在添加元素时实际上调用<br /> 了hashmap的put方法·,元素存放的数据key部分不可重复,而 且存入与取出的顺序不同。<br /> ---->TreeSet底层为我们集合了TreeMap,在添加元素时实际上调用 <br /> 了Treemap的put方法·,元素存放的数据key部分不可重复,而 <br /> 且存入与取出的顺序不同。<br />---->Map体系:<br /> ---->HashMap:可以以key-value的形式去存放数据,key与value都是<br /> 允许为空的,不是线程安全的集合,底层是hash散列(hash桶)<br /> <br /> ---->HashTable:线程安全版的hashMap,执行效率是不高的,key和<br />value都是不允许重复的
---->TreeMap:由key值自动排序,存入元素的引用是我们自定义<br /> 的,该引用必须实现比较接口,<br />---->Comparable<泛型>,重写比较规则,不如就会报异常转换异常<br />---->properties:继承了HashTabe,线程安全的,数据集合流对象高效读取文件配置;