一、自动装箱、拆箱;

  • java中所有基本类型都有对应的封装类(引用数据类型)
  • 我们学习的集合只能存放引用数据

1.1 数据类型转换

  1. 类型的容器;Java.lang
  2. 自动装箱:基本数据类型转为引用数据类型;

    对应的封装类:int➡️Integer。int i = 1;自动装箱Integer i1 = i ; boolean : Boolean

double :Double ;float:Float ; char :Charater ;byte :Byte ; short : Short ;long:Long

  1. 自动拆箱:引用数据类型转为基本数据类型;

1.2 数据比较与内存表示

  1. 引用数据类型在定义过程左边声明变量在栈中,右边new在堆中,具体的基本数据类型存在方法区的常量池内。(注明:相同的的基本数据类型不会多次在常量池中开辟内容,常量池中的内容不会重复。)
  2. 指向问题
  • 可以结合jvm内存的具体图来理解:例如a,a的变量名声明在栈中,new Integer()声明在堆中,100存储在方法区的产量池内。
  • 由a在栈中指向堆中的new Integer()的地址,在由new Integer()指向100存储在方法区的产量池内的地址。
  • 如果进行 == 比较:比较的是内存地址; a与c都是引用数据类型但是比较返回false,因为a变量内保存的是堆中的地址,c内保存的直接是常量池中100

    1. 对应的地址。

    ```java Integer a = new Integer(100); Integer b = new Integer(100);

Integer c = 100;

int d = 100;

  1. 3. 如图表示引用数据类型的内存存储。
  2. ![@_`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)
  3. <a name="C3fcF"></a>
  4. ## 二、集合
  5. 1. 结构:Iterable最高 → Collection →(List )
  6. 1. 集合是容器,最能存放引用数据类型;
  7. 每个集合的实现类底层封装了一种数据结构;<br /> 每个集合都可以获取迭代器接口提供的迭代方法;
  8. <a name="ZlCoQ"></a>
  9. ### 2.1 Collection接口
  10. 3. collection接口引用的子类对象,如果通过多态的方式添加数据,只能通过collection继承的迭代器来遍历出数据元素
  11. 3. Iterable仅有一个方法(遍历元素的迭代器)
  12. ```java
  13. import com.eagleslab.pojo.User;
  14. import java.util.ArrayList;
  15. import java.util.Collection;
  16. import java.util.Iterator;
  17. public class CollectionDemo01 {
  18. public static void main(String[] args) {
  19. //创建集合对象
  20. Collection collection = new ArrayList();
  21. Collection collection1 = collection;
  22. //添加元素
  23. collection.add(1000);//自动装箱
  24. collection.add(true);//自动装箱
  25. collection.add(new Object());
  26. collection.add("hello world");
  27. collection.add(new User());
  28. //查看元素个数
  29. System.out.println(collection.size());
  30. //清空集合中的元素
  31. //collection.clear();
  32. //查看元素个数
  33. System.out.println(collection.size());
  34. //返回值指的是是否删除成功
  35. boolean b = collection.remove("hello world");
  36. System.out.println(collection.size());
  37. System.out.println("是否删除成功 "+b);
  38. //判断集合是否为空
  39. boolean empty = collection.isEmpty();
  40. System.out.println("集合是否为空 "+empty);
  41. //判断集合中是否包含某一个元素
  42. boolean contains = collection.contains("hello world");
  43. boolean contains1 = collection.contains(1000);
  44. System.out.println("是否包含 hello world "+contains);
  45. System.out.println("是否包含 1000 "+contains1);
  46. //比较集合对象是否相等
  47. boolean equals = collection.equals(collection1);
  48. //遍历集合的方法
  49. Iterator iterator = collection.iterator();//获取集合的迭代器对象
  50. /*
  51. * iterator.hasNext() 判断集合中是否存在下一个元素 存在返回true 否则返回false
  52. * iterator.next()指针往下走一个单元,并且将指向的元素返回
  53. * */
  54. while (iterator.hasNext()){
  55. //指针往下走一个单元,并且将指向的元素返回
  56. Object next = iterator.next();
  57. System.out.println(next);
  58. }
  59. }
  60. }

2.2、List接口(底层实现collection接口)

  • 一个有序的集合,可以包含重复的元素;提供了按照索引访问元素的方(相较于collection);有序指存入和取出的顺序。
  • 遍历方式:

    1. 可以用list.get(i)来遍历,list底层封装了数组,根据下标来取值。<br /> 也可以用,Iterator迭代器遍历

2.2.2 ArrayList

  1. 性能:底层数组,数组特性,查询效率高,增删效率低;
  2. 扩容机制:最初默认初始容量是10(10个元素),当数据超过10个就会触发扩容机制
  3. 扩容因子:(加载因子)是1.5
  4. 线程安全:否

2.2.3、LinkedList

  1. 定义:基于链表结构,操作方法于ArrarList基本一致;
  2. 性能:基于链表(查询效率低,随机增删效率高)的区别。
  3. 扩容机制:对容量没有要求;

2.2.4 Vector

  1. 性能:线程安全,集合的所有方法都增加了线程安全关键字,所以效率低,使用较少。
  2. 扩容机制:初试容量为0,扩容因子2.0。

2.2.5 Arraylist与vector的区别

  1. 两个集合底层都封装了数据这一数据结构;
  2. arrarylist是线程不安全的,vector是线程安全的。所有的封装方法都相同。
  3. 扩容机制不同,arrarylist与vector最初默认初始容量都是10(10个元素),当数据超过10个就会触发扩容机制,Arrrylist扩容因子是1.5,vector扩容因子是2.0;
  4. arrarylist相对于vector每个方法多了一个线程同步的关键字

2.3、遍历方法

  1. Iterator迭代器:iterator.hasNext()相当于一个指针,判断集合下一个单元是否含有元素返回true

    如果有,就返回下一个数据存并指向下一个单元;
    一但确定了迭代器,就不要改动集合数据,集合list去修改数据用迭代器去修改数据

  2. 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之后引入的新特性,强制让集合只能存放某一种数据类型)

  1. 结构 :钻石表达式<数据表达式>。 原本是默认数据类型——所有引用数据类型都能装
  2. ArrayList<数据类型> 名 = new ArrayList<>();后一个钻石表达式内省略;
  3. 创建集合对象:ArraryList<父类> 对象 = new ArraryList<>( );

    1. 对象.add(new 父类());<br /> 对象.addnew 子类());父类对子类对象的引用;
  4. 范型相当于一个数据类型,可以去继承也可指定父类,可以自定义。

  5. 为了固定一个类型,提高了安全性,不必担心类型转换错误,因为类型不按要求会报错。
    1. Public class person< E>;
    2. Private.E e;
    3. Public void get(E e){}

三、Map接口

3.1 HashMap集合

  1. 存放键值对(key-value)的容器;

    1. //创建集合对象
    2. Map map = new HashMap();
    3. //添加对象(键值对)
    4. map.put(“name ,”jack”);
    5. (“key”,“value”).size()
    6. // .containsvalue(“需要判断是否存在的值”)
    7. // .equeals() //由key来获取value.get(“key”)
    8. //把map集合中的key转为set集合;
    9. Set set = map.keyset();
    10. putAll一个集合的所有元素复制到另一个集合,
    11. //删除或者查询都是通过key,根据key来删除整个键值map.remove(“key”)
  2. value是key的一个替代品,我们在以后的操作时是根据key去操作的。map中key是不能重复的,value可以重复,如果添加的元素key重复,后添加的元素会覆盖前者

  3. Map没有迭代器;先用keyset把key值全部给set对象,用set对象的迭代器来遍历;

  4. map.entryset() 将map集合转为set集合:重要

    entryset的范型是一个内部接口;
    Set>entries = map名.entrySet

3.2 Hash散列/Hash桶:

数组和链表的结合体:想把数组和链表的有点都发挥出来。横向看是数组,纵向看是挂载着一些链表。

  1. HashCode()方法会随机生成hash码值我们添加的元素是引用数据类型,那一定会继承object类的hashcode方法;

  2. 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

  1. 区别:HashMap key-value可以为一次空注意多次key重复的覆盖问题; hashTable不能为空,因为他是线程安全的;
  2. 线程安全性:HashTable是线程同步的,也称线程安全;hashtabe是线程安全版的hashmap,其余所有操作都相同;和arrrylist与vectct一样,
  3. hashmap的执行效率要比hashtable高,因为hahstable 添加了线程安全同步字;在多线程的情况下执行效率不高,但是以后开发中可以通过别的途径来解决线程同步的问题;

五、treeMap集合

(底层封装了二叉树)可以根据存入数据的key的值来自动排序
  1. 如果你使用treeset或者terrmap时由于涉及比较,

    故:如果使用引用数据类型一定要实现Comparable进行数据强转;

  2. 实现与重写Comparable接口:

  • 整形或者字符串类型(在代码底层呢已经实现了Comparable接口重写了比较规则)的都可以进行排序;
  • 参与比较的引用数据类型/实例必须重写实现底层的comparable接口,否则就会报错 ;
  • 重写比较规则:由小到大的遍历,通过比较之后返回int类型的数据,小于0则返回左子树,大于0则返回右子树。返回正数负数还是0;
  1. 案例:使用hashmap统计一组字符数据中每个字母出现的次数;

步骤:先转为字符数组,在通过map,在entreyset,foreach遍历
matchs(“//w”)排除一些字符。 //W排除字符;//w排除非字符;/w排除下划线;

六、treeSet

添加数据的的本质与map相同;和hashmap与hashset的关系相同。
  1. 和treeMap一样,
  2. 无序不可重复,有覆盖,(可能不对)排序过程比较的是内容。

再hashSet中

  • 自定义的引用数据类型默认情况下默认比较的是内存地址(双等号比较);
  • 而非自定义的数据类型比较的是内容,因为重写了equals方法比较的是内容。
  • —>所以要在自定义的数据类型,需要重写equals方法,让其输入对象时比较的是内容而不是内存地址。

七、Properties :

主要根据流对象用于读取配置文件:

  1. getProperties来读取配置文件;
  2. setproperties方法(String类型)用于存放string类型的键值对,根据key读取value
  3. 配置文件的类型就是properties;如jdbc ```java import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties;

public class PropertiesTest01 {

  1. public static void main(String[] args) {
  2. //创建流对象
  3. FileReader fileReader = null;
  4. try {
  5. fileReader = new FileReader("db.properties");
  6. //创建集合对象
  7. Properties properties = new Properties();
  8. properties.load(fileReader);
  9. String url = properties.getProperty("db.url");
  10. String driver = properties.getProperty("db.driver");
  11. String username = properties.getProperty("db.username");
  12. String password = properties.getProperty("db.password");
  13. System.out.println(url);
  14. System.out.println(driver);
  15. System.out.println(username);
  16. System.out.println(password);
  17. } catch (IOException ioException) {
  18. ioException.printStackTrace();
  19. }finally {
  20. //关闭流对象
  21. try {
  22. fileReader.close();
  23. } catch (IOException ioException) {
  24. ioException.printStackTrace();
  25. }
  26. }
  27. }

}

```

八、集合体系总结:

——>collection体系
——>List接口
——>ArrayList:底层数组,数组特性,查询效率高,增删效率低;
——>Vector:本身线程不安全的,默认初试容量是10,超过则触发扩 容机制,扩容因子是1.5
——>LinkedLIst:低层封装了单项链表结构,所以该集合有链表的所 有特性,查询效率不高,但是增删效率高,而且再linkerlist底
层封装了队列,可以调用入队出队方法。

  1. ---->Set接口<br /> ---->HashSet底层为我们集合了HashMap,在添加元素时实际上调用<br /> hashmapput方法·,元素存放的数据key部分不可重复,而 且存入与取出的顺序不同。<br /> ---->TreeSet底层为我们集合了TreeMap,在添加元素时实际上调用 <br /> Treemapput方法·,元素存放的数据key部分不可重复,而 <br /> 且存入与取出的顺序不同。<br />---->Map体系:<br /> ---->HashMap:可以以key-value的形式去存放数据,keyvalue都是<br /> 允许为空的,不是线程安全的集合,底层是hash散列(hash桶)<br /> <br /> ---->HashTable:线程安全版的hashMap,执行效率是不高的,key和<br />value都是不允许重复的
  2. ---->TreeMap:由key值自动排序,存入元素的引用是我们自定义<br /> 的,该引用必须实现比较接口,<br />---->Comparable<泛型>,重写比较规则,不如就会报异常转换异常<br />---->properties:继承了HashTabe,线程安全的,数据集合流对象高效读取文件配置;