A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

鲤鱼不吃肉

初级黑马

  • 黑马币:24

  • 帖子:9

  • 精华:0

© 鲤鱼不吃肉 初级黑马   /  2018-5-2 13:10  /  758 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

集合体系结构
集合体系图

   在最顶层的父接口Collection中一定定义了所有子类集合的共同属性和方法,因此我们首先需要学习Collection中共性方法,然后再去针对每个子类集合学习它的特有方法
集合的体系结构:
*          由于不同的数据结构(数据的组织,存储方式),所以Java为我们提供了不同的集合,
*          但是不同的集合他们的功能都是相似,不断的向上提取,将共性抽取出来,这就是集合体系结构形成的原因
*  
*  体系结构:
*                  怎么学习?最顶层开始学习,因为最顶层包含了所有的共性
*                  怎么使用?使用最底层,因为最底层就是具体的实现
Collection中的常用功能
boolean add(Object e): 向集合中添加元素
void clear():清空集合中所有元素
boolean contains(Object o):判断集合中是否包含某个元素
boolean isEmpty():判断集合中的元素是否为空
boolean remove(Object o):根据元素的内容来删除某个元素
int size():获取集合的长度
Object[] toArray():能够将集合转换成数组并把集合中的元素存储到数组中
迭代器
   java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。
Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
集合中把这种取元素的方式描述在Iterator接口中。Iterator接口的常用方法如下
hasNext()方法:判断集合中是否有元素可以迭代
next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。

并发修改异常
并发修改异常产生原因:
当使用迭代器遍历集合的时候,使用了集合中的 增加/删除 方法,导致并发修改异常产
并发修改异常解决方案:
   A:不使用迭代器遍历集合,就可以在遍历的时候使用集合的方法进行增加或删除(普通for循环)
   B:依然使用迭代器遍历,那么就需要使用Iterator的子接口ListIterator来实现向集合中添加  ListIterator it = collection.ListIterator();
          It.add(Object);


泛型
在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。
泛型的使用
  当类上定义<>的时候就可以使用泛型,例如ArrayList类的定义:
  Class  ArrayList<E>,那么我们在创建ArrayList对象的时候就可以指定<>中E的类型
  ArrayList<String> al=new ArrayList<String>(),那么String就把E替换掉了

使用集合存储自定义对象并遍历
* 由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常,
* 所以java为了解决这个问题,给我们提供了一种机制,叫做泛型
*
* 泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点
* 泛型好处:
*                         避免了类型转换的问题
*                         可以减少黄色警告线
*                         可以简化我们代码的书写
*
* 什么时候可以使用泛型?
*                 问API,当我们看到<E>,就可以使用泛型了
增强for
增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
常见数据结构
数组
数组,采用该结构的集合,对元素的存取有如下的特点:
查找元素快:通过索引,可以快速访问指定位置的元素
增删元素慢 ,每次添加元素需要移动大量元素或这创建新的数组

链表
链表,采用该结构的集合,对元素的存取有如下的特点:
A:多个节点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
B:查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
C:增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可

栈&队列
A:堆栈,采用该结构的集合,对元素的存取有如下的特点:
先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
B:队列,采用该结构的集合,对元素的存取有如下的特点:
先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,安检。排成一列,每个人依次检查,只有前面的人全部检查完毕后,才能排到当前的人进行检查。

  
List子体系
List子体系特点
                   A:有序的(存储和读取的顺序是一致的)
B:有整数索引
C:允许重复的
List的特有功能
          void add(int index, E element) :将元素添加到index索引位置上
                E get(int index) :根据index索引获取元素
                Object remove(int index) :根据index索引删除元素,并返回被删除的元素
                Object set(int index, E element):将index索引位置的的元素设置为element,并返回被置换的元素。
LinkedList特有功能
LinkedList底层使用的是链表结构,因此增删快,查询相对ArrayList较慢
void addFirst(E e) :向链表的头部添加元素
void addLast(E e):向链表的尾部添加元素
E getFirst():获取链头的元素,不删除元素
E getLast():获取链尾的元素,不删除元素
E removeFirst():返回链头的元素并删除链头的元素
E removeLast():返回链尾的元素并删除链尾的元素

List的常用子类:
*                 ArrayList
*                         底层是数组结构,查询快,增删慢
*                 LinkedList
*                         底层结构是链表,查询慢,增删快
*
* 如何选择使用不同的集合?
*                 如果查询多,增删少,则使用ArrayList
*                 如果查询少,增删多,则使用LinkedList
*                 如果你不知道使用什么,则使用ArrayList


作业:模拟堆栈,模拟getIndex和contains方法。




























HashSet集合
Set接口的特点   
Set体系的集合:
    A:存入集合的顺序和取出集合的顺序不一致
    B:没有索引
    C:存入集合的元素没有重复
HashSet唯一性原理
if (元素A hash值 == 元素B hash值 && (元素A== 元素B ||元素A equals 元素B)) {
如果if通过,则去重该元素
}
   规则:新添加到HashSet集合的元素都会与集合中已有的元素一一比较
        首先比较哈希值(每个元素都会调用hashCode()产生一个哈希值)
             如果新添加的元素与集合中已有的元素的哈希值都不同,新添加的元素存入集合
             如果新添加的元素与集合中已有的某个元素哈希值相同,此时还需要调用equals(Object obj)比较
                   如果equals(Object obj)方法返回true,说明新添加的元素与集合中已有的某个元素的属性值相同,那么新添加的元素不存入集合
                   如果equals(Object obj)方法返回false, 说明新添加的元素与集合中已有的元素的属性值都不同, 那么新添加的元素存入集合
hashCode方法优化:
   如果让hashCode()方法返回一个固定值,那么每个新添加的元素都要调用equals(Object obj)方法比较,那么效率较低,可以通过复杂的运算来降低HashCode的重复率。
   只需要让不同属性的值的元素产生不同的哈希值,那么就可以不再调用equals方法比较提高效率
        @Override
        public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + age;
                result = prime * result + ((name == null) ? 0 : name.hashCode());
                return result;
        }


Collections中的方法(工具类)
/*
* Collections:
* 面试题:Collection和Collections有什么区别?
*                 Collection是集合体系的最顶层,包含了集合体系的共性
*                 Collections是一个工具类,方法都是用于操作Collection
*
*/
public class CollectionsDemo {
        public static void main(String[] args) {
                //static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(4);
                Collections.swap(list, 0, 1);   
               
                System.out.println(list);
       
        }

        private static void method6() {
                //static void  sort(List<T> list) :按照列表中元素的自然顺序进行排序
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(4);
                list.add(3);
                list.add(2);
               
                Collections.sort(list);
                System.out.println(list);
        }

        private static void method5() {
                //static void shuffle(List list):傻否,随机置换  
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(2);
                list.add(3);
                list.add(4);
                Collections.shuffle(list);
                System.out.println(list);
        }

        private static void method4() {
                //static void reverse(List list)  :反转
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(2);
                list.add(3);
                list.add(4);
               
                Collections.reverse(list);
                System.out.println(list);
        }

        private static void method3() {
                //static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素
                List<String> list = new ArrayList<String>();
                list.add("hello");
                list.add("world");
                list.add("java");
                System.out.println(list);
               
                Collections.fill(list, "android");
               
                System.out.println(list);
        }

        private static void method2() {
                //static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表
                //注意:目标列表的长度至少等于源列表的长度
                //创建源列表
                List<String> src = new ArrayList<String>();
                src.add("hello");
                src.add("world");
                src.add("java");
               
                //创建目标列表
                List<String> dest = new ArrayList<String>();
                dest.add("java");
                dest.add("java");
                dest.add("java");
                dest.add("java");
                Collections.copy(dest, src);
                System.out.println(dest);
        }

        private static void method() {
                //static int  binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置
                List<Integer> list = new ArrayList<Integer>();
                list.add(1);
                list.add(2);
                list.add(3);
                list.add(4);
               
                int index = Collections.binarySearch(list, 4);
                System.out.println(index);
        }
}


斗地主案例
具体规则:
        1. 组装54张扑克牌
2. 将54张牌顺序打乱
        3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
        4. 查看三人各自手中的牌、底牌
案例代码五:

package com.itheima_03;

import java.util.ArrayList;
import java.util.Collections;

/*
*        模拟斗地主发牌
       
        买牌
        洗牌
        发牌

*/
public class CollectionsTest {
        public static void main(String[] args) {
                //买牌
                String[] arr = {"黑桃","红桃","方片","梅花"};
                String[] arr2 = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
               
                ArrayList<String> box = new ArrayList<String>();
                //添加每张牌
                for (int i = 0; i < arr.length; i++) {
                        //获取每一个花色
                        for (int j = 0; j < arr2.length; j++) {
                                //获取每一个数
                                box.add(arr[i] + arr2[j]);
                        }
                       
                }
                box.add("大王");
                box.add("小王");
                //System.out.println(box.size());
               
                 //洗牌
                Collections.shuffle(box);
                //System.out.println(box);
               
                 //发牌
                ArrayList<String> 林志玲 = new ArrayList<String>();
                ArrayList<String> 林心如 = new ArrayList<String>();
                ArrayList<String> 舒淇 = new ArrayList<String>();
               
                //留三张底牌给地主
                for (int i = 0; i < box.size() - 3; i++) {
                        /*
                         *  i = 0;i % 3 = 0;
                         *  i = 1;i % 3 = 1;
                         *  i = 2;i % 3 = 2;
                         *  i = 3;i % 3 = 0;
                         *  i = 4;i % 4 = 1;
                         *  i = 5;i % 5 = 2;
                         */
                       
                        if(i % 3 == 0) {
                                林志玲.add(box.get(i));
                        }
                        else if(i % 3 == 1) {
                                林心如.add(box.get(i));
                        }
                        else if(i % 3 == 2) {
                                舒淇.add(box.get(i));
                        }
                }
               
                System.out.println("林志玲:" + 林志玲);
                System.out.println("林心如:" + 林心如);
                System.out.println("舒淇:" + 舒淇);
         
       
                System.out.println("底牌:");
        /*        System.out.println(box.get(box.size() - 1));
                System.out.println(box.get(box.size() - 2));
                System.out.println(box.get(box.size() - 3));*/
               
                for (int i = box.size() - 3; i < box.size(); i++) {
                        System.out.println(box.get(i));
                }
        }
       
}









HashMap集合
Map接口概述
我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图。
A:Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储
B:Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
C:Collection中的集合称为单列集合,Map中的集合称为双列集合。
需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
Map常用功能
A:映射功能:
   V put(K key, V value) :以键=值的方式存入Map集合
B:获取功能:
     V get(Object key):根据键获取值
int size():返回Map中键值对的个数
C:判断功能:
    boolean containsKey(Object key):判断Map集合中是否包含键为key的键值对
           boolean containsValue(Object value):判断Map集合中是否包含值为value键值对
boolean isEmpty():判断Map集合中是否没有任何键值对
D:删除功能:
  void clear():清空Map集合中所有的键值对
  V remove(Object key):根据键值删除Map中键值对
E:遍历功能:
  Set<Map.Entry<K,V>> entrySet():将每个键值对封装到一个个Entry对象中,再把所有Entry的对象封装到Set集合中返回
  Set<K> keySet() :将Map中所有的键装到Set集合中返回
  Collection<V> values():返回集合中所有的value的值的集合
Map的两种遍历方式
Map的第一种遍历方式:
*                         首先召集所有的丈夫
*                         遍历所有的丈夫
*                         获取每一个丈夫
*                         让每一个丈夫去找他自己的媳妇
public class MapDemo4 {
        public static void main(String[] args) {
                //创建Map对象
                Map<String,String> map = new HashMap<String,String>();
                //添加映射关系
                map.put("谢婷疯", "张箔纸");
                map.put("陈关西", "钟欣桶");
                map.put("李亚碰", "王飞");
                //遍历Map对象
               
                //首先召集所有的丈夫
                Set<String> keys = map.keySet();
                //遍历所有的丈夫
                for (String key : keys) {
                        //让每个丈夫去找他自己的媳妇就可以了
                        String value = map.get(key);
                        System.out.println("丈夫:" + key + "---" + "媳妇:" + value);
                }
               
        }
}


Map的第二种遍历方式:
*                 通过结婚证对象来获取丈夫和媳妇
*                利用entrySet()方法遍历

public class MapDemo5 {
        public static void main(String[] args) {
                //创建Map对象
                Map<String,String> map = new HashMap<String,String>();
                //添加映射关系
                map.put("尹志平", "小龙女");
                map.put("令狐冲", "东方菇凉");
                map.put("玄慈", "叶二娘");
                //获取所有的结婚证对象
                Set<Map.Entry<String,String>> entrys = map.entrySet();
                //遍历包含了结婚证对象的集合
                for (Map.Entry<String, String> entry : entrys) {
                        //获取每个单独的结婚证对象
                        //通过结婚证对象获取丈夫和媳妇
                        String key = entry.getKey();
                        String value = entry.getValue();
                        System.out.println("丈夫:" + key + "---" + "媳妇:" + value);
                }
               
        }
}


可变参数(了解)
知识概述
当参数不确定的时候, 类型要明确
Java可以把多个参数直接帮我们转成数组

理解: 可变参数本质就是一个长度可变的数组.

格式:

        实参: 一个参数一个参数的传递
        形参: 类型…变量名
       
注意
在可变参数之后不可以再追加参数
参数的数量定义, 可以给多个甚至也可以一个都不不给
案例代码:
Public static int getSum(int…num){
        int sum = 0;
                for(int i = 0; i < num.length; i++){
                        sum+=num[i];
}
return sum;
}

2 个回复

倒序浏览
6666666666666
回复 使用道具 举报
123456666666666
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马