首页 > 编程语言 > 详细

Java基础笔记3

时间:2020-04-27 22:13:24      阅读:59      评论:0      收藏:0      [点我收藏+]

Java基础笔记3

集合

1、集合和数组都是对多个数据进行存储操作的结构,简称java容器

说明:此时的存储,主要是指内存层面的不涉及持久化的存储

2、数组特点:

  • 一旦初始化后,长度确定了

  • 一旦定义好,元素类型也确定了

    缺点:

  • 一旦初始化后,长度不可修改

  • 数组中提供的方法有限,对于删除,插入数据等操作,非常不便,同时效率不高

  • 获取数组中实际元素的个数无现成方法可用

  • 数组存储数据的特点:有序、可重复,对于无序、不可重复的需求,无法满足

Java集合分为Collection和Map两种体系

集合框架

  1. Collection接口:单列集合,用来存储一个一个的对象

    List接口:存储有序的,可重复的数据

    实现类:ArrayList、LinkedList、Vector

    Set接口:存储无序的,不可重复的数据

    实现类:HashSet、LinkedHashSet、TreeSet

  2. Map接口:双列集合,用来存储一对一对(key - value)的数据

    实现类:HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

Collection接口中的API

        Collection coll = new ArrayList();
        coll.add("AA");
        coll.add("BB");
        coll.add(123);
        coll.add(new Date());
        System.out.println(coll.size());//4

        Collection coll1 = new ArrayList();
        coll1.add(456);
        coll1.add("CC");
        coll.addAll(coll1);
        //addAll(Collection c)
        System.out.println(coll.size());//6

        System.out.println(coll.isEmpty());//false

        coll.clear();

        System.out.println(coll.isEmpty());//true
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        boolean contains = coll.contains(123);
        System.out.println(contains);//true
        //比较时会调用obj的equals方法
        System.out.println(coll.contains(new String("Tom")));//true

        Collection coll1 = Arrays.asList(123,456);
        System.out.println(coll.containsAll(coll1));//true

//        boolean remove = coll.remove(123);
//        System.out.println(remove);//true

//        coll.removeAll(coll1);
//        //差集
//        System.out.println(coll);//[Tom, false]
        //获取交集
        Collection coll2 = Arrays.asList(123,456,789);
//        coll.retainAll(coll2);
//        System.out.println(coll);//[123, 456]
        //ArrayList有序
        Collection coll3 = Arrays.asList(123,456,789);
        System.out.println(coll2.equals(coll3));//true
        coll3 = Arrays.asList(456,123,789);
        System.out.println(coll2.equals(coll3));//false
        System.out.println(coll.hashCode());//7639761
        //集合->数组
        Object[] objects = coll.toArray();
        for (Object o: objects
             ) {
            System.out.println(o);
        }
        //数组 -> 集合
        List<Object> objects1 = Arrays.asList(objects);

        Object[] objects2 = coll.toArray();
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        Iterator iterator = coll.iterator();
//        System.out.println(iterator.next());//123
        //判断是否含有下一个元素
        while (iterator.hasNext()){
            //指针下移,并将元素返回
            System.out.println(iterator.next());
        }

List接口

动态数组,存储有序的,可重复的数据

ArrayList、LinkedList、Vector相同点:都实现了List接口,存储数据的特点相同,存储有序的、可重复的数据

ArrayList:作为List接口的主要实现类,线程不安全的,效率高,底层使用Object[] elementData存储

源码分析:

jdk7:

ArrayList list = new ArrayList();//底层创建了长度为10的Object[] elementData数组
list.add(123);//elementData[0] = new Integer(123);
...
list.add(11);//如果此时的添加导致底层elementData数组容量不够,则扩容
//默认情况下,扩容为原来容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中
//结论:建议开发中使用带参的构造器,避免多次扩容
ArrayList list = new ArrayList(50);

jdk8中的变化:

ArrayList list = new ArrayList();//底层Object[] elementData数组初始化为{},并没有创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度为10的数组,并将数据添加到elementData中
//扩容操作与jdk7.0一样
//延迟了数组的创建,节省了内存

Vector:作为List接口的古老实现类,线程安全的,效率低,底层使用Object[] elementData存储

初始化长度为10

扩容:原来的2倍

LinkedList:对于频繁的插入和删除操作,效率比ArrayList高,底层使用双向链表存储

源码分析:

LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象

List接口中常用方法

        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add(new String("Tom"));
        list.add(false);
        list.add(456);
        list.add(0,"BB");
        System.out.println(list.toString());//[BB, 123, 456, Tom, false, 456]
        List list1 = Arrays.asList(1,2,3);
        list.addAll(list1);
        System.out.println(list.size());//9
        int i = list.indexOf(456);
        System.out.println(i);//2 不存在返回-1
        int i1 = list.lastIndexOf(456);
        System.out.println(i1);//5
        Object remove = list.remove(0);
        System.out.println(remove);//BB
        System.out.println(list);//[123, 456, Tom, false, 456, 1, 2, 3]
        list.set(0,"AAA");
        System.out.println(list);//[AAA, 456, Tom, false, 456, 1, 2, 3]
        List list2 = list.subList(0, 3);
        System.out.println(list2);//[AAA, 456, Tom]
        System.out.println(list);//[AAA, 456, Tom, false, 456, 1, 2, 3]
        System.out.println(list.get(1));//456

Set 接口

存储无序的、不可重复的数据

无序性:不等于随机性,以HashSet为例,存储的数据在底层数组中并非按照数组的索引的顺序添加,而是根据数据的哈希值

不可重复性:保证添加的元素按照equal方法判断时,不能返回true,即相同的元素只能添加一个

HashSet:作为Set接口的主要实现类,线程不安全的,可以存储null值,底层:数组+链表的结构

添加元素的过程:

我们向HashSet中添加元素a,首先调用元素a所在类的HashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出HashSet底层数组中的存放位置(即索引位置),判断数组此位置上是否已经有元素:

如果数组此位置上没有其它元素,则元素a添加成功。(1)

如果数组此位置上有其它元素b(或以链表形式存在的多个元素),则比较元素a和元素b的哈希值,如果哈希值不相同,则添加成功(2),如果相同,则需要调用元素a所在类的equals方法,若返回true,元素a添加失败,返回false,元素a添加成功。(3)

对于2和3添加成功的情况,元素a与已经存在指定索引位置上数据以链表的方式存储。

jdk7:元素a放在数组中,指向原来的元素

jdk8:原来的元素在数组中,指向元素a

(总结:七上八下)

1、Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法

2、重写的hashCode()和equals()尽可能保持一致性,相等的对象必须具有相等的散列码

LinkedHashSet:HashSet的子类:遍历其内部,可以按照添加的顺序遍历,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据

优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

TreeSet:使用红黑树存储,可以按照添加对象的指定属性进行排序

1、向TreeSet中添加的数据,要求是相同类的对象

2、两种排序方式:自然排序(实现Comparable接口)和定制排序

3、自然排序中,比较两个对象是否具有相同的标准为compareTo()返回0,不是equals()

4、定制排序中,比较两个对象是否具有相同的标准为compare()返回0,不是equals()

Map接口(1.2)

双列集合,用来存储一对一对(key - value)的数据

实现类:HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

HashMap:作为Map的主要实现类:线程不安全的,效率高,可以存储null的key和value

LinkedHashMap(1.4):HashMap的子类,保证遍历map元素时,可以按照添加的顺序实现遍历

原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素,对于频繁的遍历操作,执行效率高于HashMap

TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序和定制排序,底层使用红黑树

//向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
//因为要按照key进行排序:自然排序、定制排序

Hashtable(1.0):作为古老的实现类:线程安全的,效率低,不能存储null的key和value

Properties: Hashtable的子类,常用来处理配置文件,key和value都是String类型

HashMap的底层:数组+链表(jdk7以前)

数组+链表+红黑树(jdk8)

Map结构:

Map中的key: 无序的,不可重复的,使用Set存储所有的key,key所在的类重写equals()和hashCode()

Map中的value: 无序的,可重复的,使用Collection存储所有的value,value所在的类重写equals()

一个键值对:key-value构成了一个entry对象

Map中的entry:无序的,不可重复的,使用Set存储所有的entry

HashMap的底层实现原理:

jdk7

HashMap map = new HashMap();
//实例化后,底层创建了长度为16的一维数组Entry[] table
...
map.put(key1,value1);
//首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
//如果此位置上数据为空,此时的key1-value添加成功(1)
//如果此位置上数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和意见存在的一个或多个数据的哈希值
//如果key1的哈希值和已经存在的数据的哈希值都不相同,此时的key1-value添加成功(2)
//如果key1和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法
//如果equals()方法返回false,此时的key1-value添加成功(3)
//如果equals()方法返回true,使用value1替换value2

//补充,对于2和3,此时的key1和value1和原来的数据以链表的方式存储
//扩容:当超出临界值(容量*加载因子)(且要存放的位置非空),默认扩容为原来容量的2倍,并将原有数据复制过来

jdk8不同点

HashMap map = new HashMap();
//1.底层没有创建一个长度为16的数组
//2.jdk 8底层的数组是Node[],而非Entry[]
//3.首次调用put()方法时,底层创建长度为16的数组
//4.jdk底层结构只有数组+链表,jdk8中底层结构:数组+链表+红黑树,当数组的某一个索引位置上的元素以链表形式存在的数据个数>8,且当前数组的长度>64时,此时此索引位置上的所有数据改为红黑树存储,否则扩容(<64)。
//DEFAULT_INITIAL_CAPACITY:HashMap的默认容量:16
//DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
//threshold:扩容的临界值 = 容量*加载因子:16*0.75 = 12
//TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
//MIN_TREEIFY_CAPACITY:桶中的Node被树化是最小的hash表容量:64

LinkedHashMap

//可以按照加入的顺序遍历
//HashMap内部类:Node
//LinkedHashMap内部类:Entry,继承了Node,且多了一堆引用,before ,after

Map接口常用方法:

        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",456);
        map.put("CC",123);
        map.put("DD",789);
        map.put("AA",333);
        System.out.println(map);//{AA=333, BB=456, CC=123, DD=789}
        Map map1 = new HashMap();
        map1.put("EE",12);
        map1.put("FF",34);
        map.putAll(map1);
        System.out.println(map);//{AA=333, BB=456, CC=123, DD=789, EE=12, FF=34}

        Object cc = map.remove("CC");
        System.out.println(cc);//123
        System.out.println(map);//{AA=333, BB=456, DD=789, EE=12, FF=34}
        //map.clear();
        //System.out.println(map.size());//0

        System.out.println(map.get("BB"));//456
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);//true
        boolean b = map.containsValue(456);
        System.out.println(b);//true

        System.out.println(map.isEmpty());//false

        //遍历所有的key值
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //遍历所有的value值
        Collection values = map.values();
        for (Object o : values){
            System.out.println(o);
        }
        //遍历所有的entry
        Set set1 = map.entrySet();
        Iterator iterator1 = set1.iterator();
        while(iterator1.hasNext()){
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry)obj;
            System.out.println(entry.getKey()+ "="+ entry.getValue());
        }

Collections工具类

        //Collections:操作Collection和Map的工具类
        List list = new ArrayList();
        list.add(12);
        list.add(34);
        list.add(56);
        list.add(78);
        Collections.reverse(list);
        System.out.println(list);//[78, 56, 34, 12]

        Collections.shuffle(list);
        System.out.println(list);//[78, 56, 12, 34]

        Collections.sort(list);
        System.out.println(list);//[12, 34, 56, 78]

        Collections.swap(list,1,2);
        System.out.println(list);//[12, 56, 34, 78]

        System.out.println(Collections.max(list));//78
        System.out.println(Collections.min(list));//12

        System.out.println(Collections.frequency(list,12));//1

        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest,list);
        System.out.println(dest);//[12, 56, 34, 78]

        //转化为线程安全的list
        List list1 = Collections.synchronizedList(list);

Arrays工具类

        //java.util.Arrays: 操作数组的工具类
        int[] arr1 = new int[]{1,2,3,4};
        int[] arr2 = new int[]{1,3,2,4};
        System.out.println(Arrays.equals(arr1,arr2));//false

        System.out.println(Arrays.toString(arr1));//[1, 2, 3, 4]

        Arrays.fill(arr1,10);
        System.out.println(Arrays.toString(arr1));//[10, 10, 10, 10]

        Arrays.sort(arr2);
        System.out.println(arr2);

        int[] arr3 = {1,3,5,7,9};
        System.out.println(Arrays.binarySearch(arr3,3));//1
        System.out.println(Arrays.binarySearch(arr3,2));;//-2 未找到,负数

        int[] ints = Arrays.copyOfRange(arr3, 0, 2);
        System.out.println(Arrays.toString(ints));//[1, 3]

        int[] ints1 = Arrays.copyOf(arr3, 2);
        System.out.println(Arrays.toString(ints1));//[1, 3]

 

Java基础笔记3

原文:https://www.cnblogs.com/come-on-pxw/p/12790461.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!