zoukankan      html  css  js  c++  java
  • java学习--基础知识阶段性总结--API、集合

    方法总结:

     String类

     字符串的特点:一旦被赋值,就不能改变。

     构造方法:

      public String():空构造

      public String(byte[] bytes):把字节数组转成字符串

    public String(byte[] bytes,int index,int length):把字节数组的 一部分转成字符串

      public String(char[] value):把字符数组转成字符串

    public String(char[] value,int index,int count):把字符数组的 一部分转成字符串

      public String(String original):把字符串常量值转成字符串

     字符串的方法:

      public int length():返回此字符串的长度。

      String类的判断功能:

      boolean equals(Object obj):比较字符串的内容是否相同,区分大小写

    boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写

      boolean contains(String str):判断大字符串中是否包含小字符串

    boolean startsWith(String str):判断字符串是否以某个指定的字符串开头

    boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾

    boolean isEmpty():判断字符串是否为空。

    注意:

       字符串内容为空和字符串对象为空。

       String s = ""; 空字符串

       String s = null; 空常量

    String类的获取功能

    int length():获取字符串的长度。

    char charAt(int index):获取指定索引位置的字符

    int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引。

    为什么这里是int类型,而不是char类型?

    原因是:'a'和97其实都可以代表'a'

    int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引。

    int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引。

    int indexOf(String str,int fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引。

    String substring(int start):从指定位置开始截取字符串,默认到末尾。

    String substring(int start,int end):从指定位置开始到指定位置结束截取字符串。

    String的转换功能:

    byte[] getBytes():把字符串转换为字节数组。

    char[] toCharArray():把字符串转换为字符数组。

    static String valueOf(char[] chs):把字符数组转成字符串。

    static String valueOf(int i):把int类型的数据转成字符串。

    注意:String类的valueOf方法可以把任意类型的数据转成字符串。

    String toLowerCase():把字符串转成小写。

    String toUpperCase():把字符串转成大写。

    String concat(String str):把字符串拼接。

    String类的其他功能:

    替换功能:

    String replace(char old,char new)

    String replace(String old,String new)

    去除字符串两空格

    String trim()

    按字典顺序比较两个字符串  

    int compareTo(String str)

    int compareToIgnoreCase(String str)

     数组方法总结:

    Arrays:针对数组进行操作的工具类。比如说排序和查找。

    1:public static String toString(int[] a) 把数组转成字符串

    2:public static void sort(int[] a) 对数组进行排序

    3:public static int binarySearch(int[] a,int key) 二分查找

    Character 类在对象中包装一个基本类型 char 的值

    此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并 将字符从大写转换成小写,反之亦然 

    构造方法:

     * *Character(char value)

     * public static boolean isUpperCase(char ch):判断给定的字符是否是大写字符

     * public static boolean isLowerCase(char ch):判断给定的字符是否是小写字符

     * public static boolean isDigit(char ch):判断给定的字符是否是数字字符

     * public static char toUpperCase(char ch):把给定的字符转换为大写字符

     * public static char toLowerCase(char ch):把给定的字符转换为小写字符

     *

     * Integer:类方法总结:

     *  * 为了对基本数据类型进行更多的操作,更方便的操作,Java就针对每一种基本数据类型提供了对应的类类型。包装类类型。

     * byte Byte

     * short Short

     * int Integer

     * long Long

     * float Float

     * double Double

     * char Character

     * boolean Boolean

     * 用于基本数据类型与字符串之间的转换。

     *  * Integer的构造方法:

     * public Integer(int value)

     * public Integer(String s)

     * 注意:这个字符串必须是由数字字符组成

     *

     * * int类型和String类型的相互转换

     *

     * int -- String

     * String.valueOf(number)

     *

     * String -- int

     * Integer.parseInt(s)

     *  

     *  * 常用的基本进制转换

     * public static String toBinaryString(int i)

     * public static String toOctalString(int i)

     * public static String toHexString(int i)

     *

     * 十进制到其他进制

     * public static String toString(int i,int radix)

     * 由这个我们也看到了进制的范围:2-36

     * 为什么呢?0,...9,a...z

     *

     * 其他进制到十进制

     * public static int parseInt(String s,int radix)

     *

     * * 注意:Integer的数据直接赋值,如果在-128到127之间,会直接从缓冲池 里获取数据 

     *

     * StringBuffer类方法总结:

     * * 线程安全(多线程讲解)

     * 安全 -- 同步 -- 数据是安全的

     * 不安全 -- 不同步 -- 效率高一些

     * 安全和效率问题是永远困扰我们的问题。

     * 安全:医院的网站,银行网站

     * 效率:新闻网站,论坛之类的

     *

     * StringBuffer:

     * 线程安全的可变字符串。

     *

     * StringBuffer和String的区别?

     * 前者长度和内容可变,后者不可变。

     * 如果使用前者做字符串的拼接,不会浪费太多的资源。

     *

     * StringBuffer的构造方法:

     * public StringBuffer():无参构造方法

     * public StringBuffer(int capacity):指定容量的字符串缓冲区对象

     * public StringBuffer(String str):指定字符串内容的缓冲区对象

     *

     * StringBuffer的方法:

     * public int capacity():返回当前容量。 理论值

     * public int length():返回长度(字符数)。 实际值

     * * StringBuffer的添加功能:

     * public StringBuffer append(String str):可以把任意类型数据添加到字 符串缓冲区里面,并返回字符串缓冲区本身

     * public StringBuffer insert(int offset,String str):在指定位置把任 意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身

     * * StringBuffer的删除功能

     * public StringBuffer deleteCharAt(int index):删除指定位置的字符,并返回本身

     * public StringBuffer delete(int start,int end):删除从指定位置开始指定位置结束的内容,并返回本身

     * * StringBuffer的替换功能:

     * public StringBuffer replace(int start,int end,String str):从start开始到end用str替换

     * * StringBuffer的反转功能:

     * public StringBuffer reverse()

     * * StringBuffer的截取功能:注意返回值类型不再是StringBuffer本身了

     * public String substring(int start)

     * public String substring(int start,int end)

     *

     *  * 1:String,StringBuffer,StringBuilder的区别?

     * A:String是内容不可变的,而StringBuffer,StringBuilder都是内容可变的。

     * B:StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高

     *

     * 2:StringBuffer和数组的区别?

     * 二者都可以看出是一个容器,装其他的数据。

     * 但是呢,StringBuffer的数据最终是一个字符串数据。

     * 而数组可以放置多种数据,但必须是同一种数据类型的。

     *

     * 3:形式参数问题

     * String作为参数传递

     * StringBuffer作为参数传递 

     *

     * 形式参数:

     * 基本类型:形式参数的改变不影响实际参数

     * 引用类型:形式参数的改变直接影响实际参数

     *

     * 注意:

     * String作为参数传递,效果和基本类型作为参数传递是一样的。

     * System类包含一些有用的类字段和方法。它不能被实例化。

     *

     * 方法:

     * public static void gc():运行垃圾回收器。

     * public static void exit(int status):终止当前正在运行的 Java 虚 拟机。参数用作状态码;根据惯例,非 0 的状态码表示异常终止。

     * public static long currentTimeMillis():返回以毫秒为单位的当前 时间

     * public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

     * 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数 组的指定位置结束。

    正则表达式规则概述:

    A:字符

    x 字符 x。举例:'a'表示字符a

    \ 反斜线字符。

    新行(换行)符 ('u000A')

    回车符 ('u000D')

    B:字符类

    [abc] a、b 或 c(简单类)

    [^abc] 任何字符,除了 a、b 或 c(否定)

    [a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围)

    [0-9] 0到9的字符都包括

    C:预定义字符类

    . 任何字符。我的就是.字符本身,怎么表示呢? .

    d 数字:[0-9]

    w 单词字符:[a-zA-Z_0-9]

    在正则表达式里面组成单词的东西必须有这些东西组成

    D:边界匹配器

    ^ 行的开头 

    $ 行的结尾 

     单词边界

    就是不是单词字符的地方。

    举例:hello world?haha;xixi

    E:Greedy 数量词 

    X? X,一次或一次也没有

    X* X,零次或多次

    X+ X,一次或多次

    X{n} X,恰好 n 次 

    X{n,} X,至少 n 次 

    X{n,m} X,至少 n 次,但是不超过 m 次 

    下面regex表示正则

     * 判断功能

     * String类的public boolean matches(String regex)

     * 分割功能

     * String类的public String[] split(String regex)

     * 根据给定正则表达式的匹配拆分此字符串。

     * 替换功能

     *   String类的public String replaceAll(String regex,String replacement)

     *   使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子 字符串。

     * 获取功能

     * Pattern和Matcher类的使用(个人推荐重点掌握,里面可以调用很多方 法)

     *

     * 模式和匹配器的基本使用顺序

    模式:

    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher(input);

    上面两步是构造了一个匹配器,有了匹配器就可以调方法

     * Random:产生随机数的类

     *

     * 构造方法:

     * public Random():没有给种子,用的是默认种子,是当前时间的毫秒值

     * public Random(long seed):给出指定的种子

     *

     * 给定种子后,每次得到的随机数是相同的。

     *

     * 成员方法:

     * public int nextInt():返回的是int范围内的随机数

     * public int nextInt(int n):返回的是[0,n)范围的内随机数

     * Math:用于数学运算的类。

     * 成员变量:

     * public static final double PI

     * public static final double E

     * 成员方法:

     * public static int abs(int a):绝对值

     * public static double ceil(double a):向上取整

     * public static double floor(double a):向下取整

     * public static int max(int a,int b):最大值 (min自学)

     * public static double pow(double a,double b):a的b次幂

     * public static double random():随机数 [0.0,1.0)

     * public static int round(float a) 四舍五入(参数为double的自学)

     * public static double sqrt(double a):正平方根

     * Date:表示特定的瞬间,精确到毫秒。

     *

     * 构造方法:

     * Date():根据当前的默认毫秒值创建日期对象

     * Date(long date):根据给定的毫秒值创建日期对象

     * public long getTime():获取时间,以毫秒为单位

     * public void setTime(long time):设置时间

     *

     * 从Date得到一个毫秒值

     * getTime()

     * 把一个毫秒值转换为Date

     * 构造方法

     * setTime(long time)

     * Date -- String(格式化)

     * public final String format(Date date)

     *

     * String -- Date(解析)

     * public Date parse(String source)

     *

     * DateForamt:可以进行日期和字符串的格式化和解析,但是由于是抽象类,所以使用具体子类SimpleDateFormat。

     *

     * SimpleDateFormat的构造方法:

     * SimpleDateFormat():默认模式

     * SimpleDateFormat(String pattern):给定的模式

     * 这个模式字符串该如何写呢?

     * 通过查看API,我们就找到了对应的模式

     * 年 y

     * 月 M

     * 日 d

     * 时 H

     * 分 m

     * 秒 s

     * Calendar:它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星 期的日期)提供了一些方法。

     *

     * public int get(int field):返回给定日历字段的值。日历类中的每个 日历字段都是静态的成员变量,并且是int类型。

     * public void add(int field,int amount):根据给定的日历字段和对应 的时间,来对当前的日历进行操作。

     * public final void set(int year,int month,int date):设置当前 日历的年月日

     * BigInteger:可以让超过Integer范围内的数据进行运算

     *

     * 构造方法:

     * BigInteger(String val)

     * public BigInteger add(BigInteger val):加

     * public BigInteger subtract(BigInteger val):减

     * public BigInteger multiply(BigInteger val):乘

     * public BigInteger divide(BigInteger val):除

     * public BigInteger[] divideAndRemainder(BigInteger val):返回商和 余数的数组

     * 构造方法:

     * public BigDecimal(String val)

     *

     * public BigDecimal add(BigDecimal augend)

     * public BigDecimal subtract(BigDecimal subtrahend)

     * public BigDecimal multiply(BigDecimal multiplicand)

     * public BigDecimal divide(BigDecimal divisor)

     * public BigDecimal divide(BigDecimal divisor,int scale,int   roundingMode):商,几位小数,如何舍取

     * 集合的由来:

     * 我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现 的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。

     * 而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的 变量,在我们目前所学过的知识里面,有哪些是容器类型的呢?

     * 数组和StringBuffer。但是呢?StringBuffer的结果是一个字符串,不 一定满足我们的要求,所以我们只能选择数组,这就是对象数组。

     * 而对象数组又不能适应变化的需求,因为数组的长度是固定的,这个时候, 为了适应变化的需求,Java就提供了集合类供我们使用。

     *

     * 数组和集合的区别?

     * A:长度区别

     * 数组的长度固定

     * 集合长度可变

     * B:内容不同

     * 数组存储的是同一种类型的元素

     * 而集合可以存储不同类型的元素

     * C:元素的数据类型问题

     * 数组可以存储基本数据类型,也可以存储引用数据类型

     * 集合只能存储引用类型

     *

     * 刚说过集合是存储多个元素的,但是呢,存储多个元素我们也是有不同需求的: 比如说,我要这多个元素中不能有相同的元素,

     * 再比如说,我要这多个元素按照某种规则排序一下。针对不同的需求,Java就 提供了不同的集合类,这样呢,Java就提供了很多个集合类。

     * 这多个集合类的数据结构不同,结构不同不重要的,重要的是你要能够存储东西, 并且还要能够使用这些东西,比如说判断,获取等。

     * 既然这样,那么,这多个集合类是有共性的内容的,我们把这些集合类的共性 内容不断的向上提取,最终就能形成集合的继承体系结构。

     *

     * 数据结构:数据的存储方式。

     *

     * Collection:是集合的顶层接口,它的子体系有重复的 (list,arraylist,linkedlist),有唯一的 (hashset,linkedhashset,Treeset),有有序的(linkedhashset,Treeset), 有无序的(hashset)。(后面会慢慢的讲解)

     *

     * Collection的功能概述:

     * 1:添加功能

     * boolean add(Object obj):添加一个元素

     * boolean addAll(Collection c):添加一个集合的元素

     * 2:删除功能

     * void clear():移除所有元素

     * boolean remove(Object o):移除一个元素

     * boolean removeAll(Collection c):移除一个集合的元素(是一个还是 所有)

     * 3:判断功能

     * boolean contains(Object o):判断集合中是否包含指定的元素

     * boolean containsAll(Collection c):判断集合中是否包含指定的集 合元素(是一个还是所有)

     * boolean isEmpty():判断集合是否为空

     * 4:获取功能

     * Iterator<E> iterator()(重点)

     * 5:长度功能

     * int size():元素的个数

     * 面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集 合有没有length()方法呢?

     * 6:交集功能

     * boolean retainAll(Collection c):两个集合都有的元素?思考元素去 哪了,返回的boolean又是什么意思呢?

     * 7:把集合转换为数组

     * Object[] toArray()

     * boolean addAll(Collection c):添加一个集合的元素

     * boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)

     * boolean containsAll(Collection c):判断集合中是否包含指定的集合元 素(是一个还是所有)

     * boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了, 返回的boolean又是什么意思呢?

     * 集合的遍历。其实就是依次获取集合中的每一个元素。

     *

     * Object[] toArray():把集合转成数组,可以实现集合的遍历

     * Iterator iterator():迭代器,集合的专用遍历方式

     * Object next():获取元素,并移动到下一个位置。

     * NoSuchElementException:没有这样的元素,因为你已经找到最后了。

     * boolean hasNext():如果仍有元素可以迭代,则返回 true。

    迭代器源码:

    boolean hasNext();

    Object next();

    }

    public interface Iterable {

        Iterator iterator();

    }

    public interface Collection extends Iterable {

    Iterator iterator();

    }

    public interface List extends Collection {

    Iterator iterator();

    }

    public class ArrayList implements List {

    public Iterator iterator() {

            return new Itr();

        }

        

        private class Itr implements Iterator {

         public boolean hasNext() {}

    public Object next(){}

        }

    }

    Collection c = new ArrayList();

    c.add("hello");

    c.add("world");

    c.add("java");

    Iterator it = c.iterator(); //new Itr();

    while(it.hasNext()) {

    String s = (String)it.next();

    System.out.println(s);

    }

    List:(面试题List的子类特点)

    ArrayList:

    底层数据结构是数组,查询快,增删慢。

    线程不安全,效率高。

    Vector:

    底层数据结构是数组,查询快,增删慢。

    线程安全,效率低。

    LinkedList:

    底层数据结构是链表,查询慢,增删快。

    线程不安全,效率高。

    List有三个儿子,我们到底使用谁呢?

    看需求(情况)。

    要安全吗?

    要:Vector(即使要安全,也不用这个了,后面有替代的)

    不要:ArrayList或者LinkedList

    查询多:ArrayList

    增删多:LinkedList

    如果你什么都不懂,就用ArrayList。

     * Vector的特有功能:

     * 1:添加功能

     * public void addElement(Object obj) -- add()

     * 2:获取功能

     * public Object elementAt(int index) --  get()

     * public Enumeration elements() -- Iterator iterator()

     * boolean hasMoreElements() hasNext()

     * Object nextElement() next()

     *

     * JDK升级的原因:

     * A:安全

     * B:效率

     * C:简化书写

     * LinkedList的特有功能:

     * A:添加功能

     * public void addFirst(Object e)

     * public void addLast(Object e)

     * B:获取功能

     * public Object getFirst()

     * public Obejct getLast()

     * C:删除功能

     * public Object removeFirst()

     * public Object removeLast()

     * List集合的特有功能:

     * A:添加功能

     * void add(int index,Object element):在指定位置添加元素

     * B:获取功能

     * Object get(int index):获取指定位置的元素

     * C:列表迭代器

     * ListIterator listIterator():List集合特有的迭代器

     * D:删除功能

     * Object remove(int index):根据索引删除元素,返回被删除的元素

     * E:修改功能

     * Object set(int index,Object element):根据索引修改元素,返回被 修饰的元素

     * List集合的特有遍历功能:

     * size()和get()方法结合使用

    * 列表迭代器:

     * ListIterator listIterator():List集合特有的迭代器

     * 该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和 next()方法。

     *

     * 特有功能:

     * Object previous():获取上一个元素

     * boolean hasPrevious():判断是否有元素

     *

     * 注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向 遍历,所以一般无意义,不使用。

     * 问题?

     * 我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果 有,我就添加一个"javaee"元素,请写代码实现。

     *

     * ConcurrentModificationException:当方法检测到对象的并发修改,但不允 许这种修改时,抛出此异常。

     * 产生的原因:

     * 迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而 迭代器却不知道,所以就报错了,这个错叫并发修改异常。

     * 其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素 的。

     * 如何解决呢?

     * A:迭代器迭代元素,迭代器修改元素

     * 元素是跟在刚才迭代的元素后面的。

     * B:集合遍历元素,集合修改元素(普通for)

     * 元素在最后添加的。

     * 泛型高级(通配符)

     * ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了

     * ? extends E:向下限定,E及其子类

     * ? super E:向上限定,E极其父类

    2:泛型(掌握)

    (1)泛型概述

    是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明 确的特殊的类型。

    (2)格式:

    <数据类型>

    注意:该数据类型只能是引用类型。

    (3)好处:

    A:把运行时期的问题提前到了编译期间

    B:避免了强制类型转换

    C:优化了程序设计,解决了黄色警告线问题,让程序更安全

    (4)泛型的前世今生

    A:泛型的由来

    Object类型作为任意类型的时候,在向下转型的时候,会隐含一 个转型问题

    B:泛型类

    C:泛型方法

    D:泛型接口

    E:泛型高级通配符

    ?

    ? extends E

    ? super E

    (5)我们在哪里使用呢?

    一般是在集合中使用。

    JDK5以后的新特性:

     * JDK5的新特性:自动拆装箱,泛型,增强for,静态导入,可变参数,枚举

     *

     * 增强for:是for循环的一种。

     *

     * 格式:

     * for(元素数据类型 变量 : 数组或者Collection集合) {

     * 使用变量即可,该变量就是元素

     *    }

     *   

     * 好处:简化了数组和集合的遍历。

     *

     * 弊端: 增强for的目标不能为null。

     * 如何解决呢?对增强for的目标先进行不为null的判断,然后在使用。

     * 静态导入:

     * 格式:import static 包名….类名.方法名;

     * 可以直接导入到方法的级别

     *

     * 静态导入的注意事项:

     * A:方法必须是静态的

     * B:如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须 加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。

     * 可变参数:定义方法的时候不知道该定义多少个参数

     * 格式:

     * 修饰符 返回值类型 方法名(数据类型…  变量名){

     *

     * }

     *

     * 注意:

     * 这里的变量其实是一个数组

     * 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最 后一个

     * public static <T> List<T> asList(T... a):把数组转成集合

     *

     * 注意事项:

     * 虽然可以把数组转成集合,但是集合的长度不能改变

     * ArrayList存储字符串并遍历。要求加入泛型,并用增强for遍历。

     * A:迭代器

     * B:普通for

     * C:增强for

     * Collection

     * |--List

     * 有序(存储顺序和取出顺序一致),可重复

     * |--Set

     * 无序(存储顺序和取出顺序不一致),唯一

     *

     * HashSet:它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。

     * 注意:虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存 储顺序,

     * 而你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数 据,就能看到效果。

     * HashSet:存储字符串并遍历

     * 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?

     * 通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode() 和equals()。

     * 步骤:

     * 首先比较哈希值

     * 如果相同,继续走,比较地址值或者走equals()

     * 如果不同,就直接添加到集合中

     * 按照方法的步骤来说:

     * 先看hashCode()值是否相同

     * 相同:继续走equals()方法

     * 返回true: 说明元素重复,就不添加

     * 返回false:说明元素不重复,就添加到集合

     * 不同:就直接把元素添加到集合

     * 如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。

     * 而String类重写了hashCode()和equals()方法,所以,它就可以把内容相 同的字符串去掉。只留下一个。

    *HashSet add()源码:

    interface Collection {

    ...

    }

    interface Set extends Collection {

    ...

    }

    class HashSet implements Set {

    private static final Object PRESENT = new Object();

    private transient HashMap<E,Object> map;

    public HashSet() {

    map = new HashMap<>();

    }

    public boolean add(E e) { //e=hello,world

            return map.put(e, PRESENT)==null;

        }

    }

    class HashMap implements Map {

    public V put(K key, V value) { //key=e=hello,world

    //看哈希表是否为空,如果空,就开辟空间

            if (table == EMPTY_TABLE) {

                inflateTable(threshold);

            }        

            //判断对象是否为null

            if (key == null)

                return putForNullKey(value);

            

            int hash = hash(key); //和对象的hashCode()方法相关

            

            //在哈希表中查找hash值

            int i = indexFor(hash, table.length);

            for (Entry<K,V> e = table[i]; e != null; e = e.next) {

             //这次的e其实是第一次的world

                Object k;

                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

                    V oldValue = e.value;

                    e.value = value;

                    e.recordAccess(this);

                    return oldValue;

                    //走这里其实是没有添加元素

                }

            }

            modCount++;

            addEntry(hash, key, value, i); //把元素添加

            return null;

        }    

        transient int hashSeed = 0;    

        final int hash(Object k) { //k=key=e=hello,

            int h = hashSeed;

            if (0 != h && k instanceof String) {

                return sun.misc.Hashing.stringHash32((String) k);

            }

            h ^= k.hashCode(); //这里调用的是对象的hashCode()方法

            // This function ensures that hashCodes that differ only by

            // constant multiples at each bit position have a bounded

            // number of collisions (approximately 8 at default load factor).

            h ^= (h >>> 20) ^ (h >>> 12);

            return h ^ (h >>> 7) ^ (h >>> 4);

        }

    }

     * LinkedHashSet:底层数据结构由哈希表和链表组成。

     * 哈希表保证元素的唯一性。

     * 链表保证元素有素。(存储和取出是一致)

     * TreeSet:能够对元素按照某种规则进行排序。

     * 排序有两种方式

     * A:自然排序

     * B:比较器排序

     *

     * TreeSet集合的特点:排序和唯一

     *

     * 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。

     * TreeSet存储自定义对象并保证排序和唯一。

     *

     * A:你没有告诉我们怎么排序

     * 自然排序,按照年龄从小到大排序

     * B:元素什么情况算唯一你也没告诉我

     * 成员变量值都相同即为同一个元素

     * 需求:请按照姓名的长度排序

     *

     * TreeSet集合保证元素排序和唯一性的原理

     * 唯一性:是根据比较的返回是否是0来决定。

     * 排序:

     * A:自然排序(元素具备比较性)

     * 让元素所属的类实现自然排序接口 Comparable

     * B:比较器排序(集合具备比较性)

     * 让集合的构造方法接收一个比较器接口的子类对象 Comparator

    2:Set集合(理解)

    (1)Set集合的特点

    无序,唯一

    (2)HashSet集合(掌握)

    A:底层数据结构是哈希表(是一个元素为链表的数组)

    B:哈希表底层依赖两个方法:hashCode()和equals()

     执行顺序:

    首先比较哈希值是否相同

    相同:继续执行equals()方法

    返回true:元素重复了,不添加

    返回false:直接把元素添加到集合

    不同:就直接把元素添加到集合

    C:如何保证元素唯一性的呢?

    由hashCode()和equals()保证的

    D:开发的时候,代码非常的简单,自动生成即可。

    E:HashSet存储字符串并遍历

    F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)

    (3)TreeSet集合

    A:底层数据结构是红黑树(是一个自平衡的二叉树)

    B:保证元素的排序方式

    a:自然排序(元素具备比较性)

    让元素所属的类实现Comparable接口

    b:比较器排序(集合具备比较性)

    让集合构造方法接收Comparator的实现类对象

    C:把我们讲过的代码看一遍即可

    (4)案例:

    A:获取无重复的随机数

    B:键盘录入学生按照总分从高到底输出

    3:Collection集合总结(掌握)

    Collection

    |--List 有序,可重复

    |--ArrayList

    底层数据结构是数组,查询快,增删慢。

    线程不安全,效率高

    |--Vector

    底层数据结构是数组,查询快,增删慢。

    线程安全,效率低

    |--LinkedList

    底层数据结构是链表,查询慢,增删快。

    线程不安全,效率高

    |--Set 无序,唯一

    |--HashSet

    底层数据结构是哈希表。

    如何保证元素唯一性的呢?

    依赖两个方法:hashCode()和equals()

    开发中自动生成这两个方法即可

    |--LinkedHashSet

    底层数据结构是链表和哈希表

    由链表保证元素有序

    由哈希表保证元素唯一

    |--TreeSet

    底层数据结构是红黑树。

    如何保证元素排序的呢?

    自然排序

    比较器排序

    如何保证元素唯一性的呢?

    根据比较的返回值是否是0来决定

    4:针对Collection集合我们到底使用谁呢?(掌握)

    唯一吗?

    是:Set

    排序吗?

    是:TreeSet

    否:HashSet

    如果你知道是Set,但是不知道是哪个Set,就用HashSet。

    否:List

    要安全吗?

    是:Vector

    否:ArrayList或者LinkedList

    查询多:ArrayList

    增删多:LinkedList

    如果你知道是List,但是不知道是哪个List,就用ArrayList。

    如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。

    如果你知道用集合,就用ArrayList。

    5:在集合中常见的数据结构(掌握)

    ArrayXxx:底层数据结构是数组,查询快,增删慢

    LinkedXxx:底层数据结构是链表,查询慢,增删快

    HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()

    TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序

  • 相关阅读:
    1 说在前面的一些话,给想学习编程的人
    springboot使用api操作HBase之shell
    HBase的安装及使用
    spring boot 多数据源加载原理
    架构师之路
    Libra和中国央行数字货币(DCEP)的对比
    微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨
    海底光缆知识科普
    jmeter安装配置教程及使用
    CountDownLatch 部分加载和同时并发业务。
  • 原文地址:https://www.cnblogs.com/bigorangehasc/p/8646141.html
Copyright © 2011-2022 走看看