第十章 集合(8)

了解:自定义排序算法:https://www.jianshu.com/p/9334567d0912

集合和数组的区别

数组:定长的 可以存放相同类型的数据 数据可以是基本类型也可以是引用类型 访问速度比较快
集合:可变长 只能存放引用类型 访问速度比数组会稍慢一些 java.util包里

集合层次结构

image.png

集合分类

collection set list map 接口

set list map区别

set:无序的,不重复 用来去重
list:有序的,数据可以重复
map: key-value键值对方式存储的 key 不可以重复,value可以重复

hashSet按hashcode排序(无序)

 @Test
  public void test1(){
      //先实例化
      HashSet s=new HashSet();
      //存放数据
      s.add("liucy");
      s.add("tanzy");
      s.add("liucy");
      s.add("zhanghs");
      s.add("shenp");
      //读出并打印
      for(Object name:s){
          System.out.println(name);
      }
  }

TreeSet按自然顺序(字母a-z,中文全拼顺序)

  @Test
  public void test2(){
      //先实例化
      TreeSet s=new TreeSet();
      //存放数据
      s.add("liucy");
      s.add("tanzy");
      s.add("liucy");
      s.add("zhanghs");
      s.add("shenp");
      //读出并打印
      for(Object name:s){
          System.out.println(name);
      }
  }


@Test
  public void test3(){
      //先实例化
      HashSet s=new HashSet();
      //存放数据
      s.add("liucy");
      s.add("tanzy");
      s.add("liucy");
      s.add("zhanghs");
      s.add("shenp");
      //沈盼出去了
      s.remove("shenp");
      //查看有没有指定元素
      boolean result=s.contains("shenp");
      System.out.println(result);
      //读出并打印
      for(Object name:s){
          System.out.println(name);
      }
  }

用泛型限制集合数据的类型
<数据类型>

  @Test
  public void test4(){
      //先实例化
      HashSet s=new HashSet();
      //存放数据
      s.add("liucy");
      s.add("liucy");
      s.add("shenp");
      //沈盼出去了
      s.remove("shenp");
      //查看有没有指定元素
      boolean result=s.contains("shenp");
      System.out.println(result);
      //读出并打印
      for(String name:s){
          System.out.println(name);
      }
  }

retainAll 保留子集

@Test
    public void test6(){
         Set s=new HashSet();
        s.add("qinggx");
        s.add("zhougb");
        s.add("dddd");
        s.add("ccccc");
        System.out.println(s);
         Set white=new HashSet();
        white.add("qinggx");
        white.add("zhougb");
        //把白名单里的人保留下来
        s.retainAll(white);
        System.out.println(s);
}

removeAll

@Test
public void test5(){
    Set s=new HashSet();
    s.add("qinggx");
    s.add("zhougb");
    s.add("dddd");
    s.add("ccccc");
    System.out.println(s);
    Set black=new HashSet();
    black.add("qinggx");
    black.add("zhougb");
    //把黑名单里的人从s里移除
    s.removeAll(black);
    System.out.println(s);
}

存放实体类

public class ClassA {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

测试方法

  @Test
  public void test5(){
      ClassA a=new ClassA();
      a.setId(16);
      a.setName("java16");
      ClassA b=new ClassA();
      b.setId(7);
      b.setName("java7");
      //先实例化
      HashSet s=new HashSet();
      s.add(a);
      s.add(b);
      for(ClassA c:s){
          System.out.println(c.getId()+" "+c.getName());
      }
      
  }

Iterator 迭代器#

@Test
public void test6() {
    ClassA a = new ClassA();
    a.setId(16);
    a.setName("java16");
    ClassA b = new ClassA();
    b.setId(7);
    b.setName("java7");
    // 先实例化
    HashSet s = new HashSet();
    s.add(a);
    s.add(b);
    //得到迭代器
    Iterator i=s.iterator();
    //hasNext() 有没有下一次元素  布尔型
    while(i.hasNext()){
    //next()方法取出
        ClassA c=(ClassA)i.next();
        System.out.println(c.getName());
        System.out.println(c.getId());
    }
}

[如何边遍历集合边删除元素--使用Iterator中的remove()方法]

否则会引发ConcurrentModifactionException()

@Test
public void test1(){
    Set s=new HashSet();
    s.add("a");
    s.add("c");
    s.add("b");
    Iterator i=s.iterator();
    while(i.hasNext()){
        String str=(String) i.next();
        //如果str为a就移除
        if("a".equals(str)){
            //错误写法s.remove(str);
            //正确
            i.remove();
        }
    }
    
    System.out.println(s);
}

课堂练习
使用Set集合,生成1-25之内不重复的7个随机整数

@Test
    public void test11() {
        HashSet hs = new HashSet();
        for (;;) {
            int r = new Random().nextInt(25) + 1;
            hs.add(r);
            if (hs.size() == 7) {
                System.out.println(hs);
                break;
            }
        }
    }


    @Test
    // 使用Set集合,生成1-25之内不重复的7个随机整数
    public void try05() {
        HashSet hs = new HashSet();
        int count = 0;
        while (count < 7) {
            Integer j = new Random().nextInt(25) + 1;
            if (hs.add(j)) {
                count++;
            }
        }
        for (Integer i : hs) {
            System.out.println(i);
        }
    }

public class test {
public static void main(String[] args)  {
HashSet h=new HashSet<>();
while (h.size()<7){
h.add((int)(Math.random()*25+1));
}
System.out.println(h);
}
}

List

List:ArrayList(常用) LinkedList Vector(线程安全)
ArrayList:有序的 可重复 底层是基于数组实现的 随机读取时速度快 适合做查询
LinkedList:底层是基于链接实现的 可以用来做栈和队列,特点是:插入和删除快,查询慢
Vector:线程安全的 做线程同步,速度会慢

栈:先进后出(类似给枪压子弹)
队列:先进先出 queue

@Test
    public void test() {
  List s=new ArrayList(); 
s.add("liucy");
        s.add("tanzy");
        s.add("liucy");
        s.add("zhanghs");
        s.add("shenp");
  for(String name:s){
      System.out.println(name);
  }
    }
    @Test
    public void test5() {
        ClassA a = new ClassA();
        a.setId(16);
        a.setName("java16");
        ClassA b = new ClassA();
        b.setId(7);
        b.setName("java7");
        // 先实例化
        List s = new ArrayList();
        s.add(a);
        s.add(b);
        for (ClassA c : s) {
            System.out.println(c.getId() + " " + c.getName());
        }
    }

ListIterator
先正向再反向读

@Test
    public void test2() {
  List s=new ArrayList(); 
s.add("liucy");
        s.add("tanzy");
        s.add("liucy");
        s.add("zhanghs");
        s.add("shenp");
        //正向输出
  ListIterator i=s.listIterator();
  while(i.hasNext()){
      System.out.println(i.next());
  }
  System.out.println("------------------->");
  //反向输出
  while(i.hasPrevious()){
      System.out.println(i.previous());
  }
    }

上面的代码如果把正向的注释掉,反向的也读不出来,原因是指针在最上面,解决方式是可以在listIterator参数里把size大小加进去。让指针先跳转到指定位置

    @Test
    public void test3() {
    List s=new ArrayList(); 
s.add("liucy");
        s.add("tanzy");
        s.add("liucy");
        s.add("zhanghs");
        s.add("shenp");
        //读取第3个元素
        String ss=s.get(3);
        System.out.println("第三个"+ss);
        //正向输出
  ListIterator i=s.listIterator(s.size());
  System.out.println("------------------->");
  //反向输出
  while(i.hasPrevious()){
      System.out.println(i.previous());
  }
    }

LinkedList常用操作

新增方法:addFirst() addLast() getFirst() getLast() removeFirst() removeLast()
addFirst() addLast()例子:

@Test
public void test() {
    LinkedList s = new LinkedList();
    s.add("liucy");
    s.add("tanzy");
    s.add("liucy");
    s.add("zhanghs");
    s.add("shenp");
    // addFirst从顶面add
    s.addFirst("NUMER ONE");
    // addLast以底部add
    s.addLast("我是倒数第一");
    s.removeFirst();
    s.removeFirst();
    s.removeLast();
    for (String name : s) {
        System.out.println(name);
    }
}

Collections类

  @Test
public void test01() {
    // 1、求最大值
    List list01 = new ArrayList();
    list01.add(20);
    list01.add(25);
    list01.add(19);
    list01.add(27);
    list01.add(28);
    // 作业:Collections(list,com)
    //Integer maxAge = Collections.max(list01);
    //System.out.println(maxAge);
    //Integer minAge = Collections.min(list01);
    //System.out.println(minAge);
    //reverse 28, 27, 19, 25, 20  只是把顺序进行了简单的反转
    //Collections.reverse(list01);
    //System.out.println("reverse之后的集合:"+list01);
    //sort从小到大排序
    //list01里的数据永远变动
    Collections.sort(list01);
    System.out.println("sort之后的集合:"+list01);
    //binarySearch 查询集合中是否存在指定的元素
    //19时-2  28-4
    //19-0 20 25-2 27 28-4
    //如果查找的对象存在,返回排序的对象索引 0

// 如果不存在,就返回负数
System.out.println(list01);
//在变化后的list01中进行操作
int result=Collections.binarySearch(list01, 23);
System.out.println("查找结果"+result);
//fill copy
// 用list02的值覆盖
Collections.copy(list01, list02);
// Collections.copy(list02, list01);
System.out.println("copy后list01-->" + list01);
System.out.println("copy后list02-->" + list02);

}

今天在学习集合中 有关对象的深度拷贝和浅拷贝 的时候,像拷贝一个ArrayList对象到另一个ArrayList对象中,正好发现Collections有一个copy方法。可是不好用啊总是报错。查看api才知道,它的capacity(容纳能力大小)可以指定(最好指定)。而初始化时size的大小永远默认为0,只有在进行add和remove等相关操作 时,size的大小才变化。然而进行copy()时候,首先做的是将desc的size和src的size大小进行比较,只有当desc的 size 大于或者等于src的size时才进行拷贝,否则抛出IndexOutOfBoundsException异常;

//想拷贝list01到list02

//复制了解即可
@Test
public void test02() {
    List list01 = new ArrayList();
    list01.add("111");
    list01.add("222");
    list01.add("333");
    list01.add("444");
    List list02 = new ArrayList();
    Collections.addAll(list02, new String[list01.size()]);
    Collections.copy(list02, list01);
    System.out.println(list02);
}


@Test
public void test02() {
    List list01 = new ArrayList();
    list01.add("111");
    list01.add("222");
    list01.add("333");
    list01.add("444");
    List list02 = new ArrayList();
    list02.addAll(list01);
    System.out.println(list01);
    System.out.println(list02);
    list01.add("555");
    System.out.println(""+list01);
    System.out.println(list02);
}

课堂练习:试验collections其他方法

作业:

1、请使用LinkedList来模拟一个队列(先进先出的特性): [必做题]
1.1 拥有放入对象的方法void put(Object o)
1.2 取出对象的方法Object get()
1.3 判断队列当中是否为空的方法boolean isEmpty();并且,编写测试代码,验证你的队列是否正确。

  2、产生10个1-100的随机数,并放到一个数组中,把数组中大于等于10的数字放到一个list集合中,并打印到控制台。
  3、双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1—33中选择;蓝色球号码从1—16中选择;请随机生成一注双色球号码。(要求同色号码不重复)

map

Map :key-value
map:HashMap基于哈希的 TreeMap基于红黑树的 LinkedHashMap

@Test
    public void test1() {
        ClassA a = new ClassA();
        a.setId(16);
        a.setName("java16");
        ClassA b = new ClassA();
        b.setId(7);
        b.setName("java7");
        // 新建一个map
        Map map = new HashMap();
        // 向map里存放数据put方法
        map.put("c7", b);
        map.put("c16", a);
        // 单个读取
        // 我知道key的情况下,根据key去查询。用get方法
        // 比如我想读取编号为c16的班级的信息
        ClassA c16 = map.get("c16");
        System.out.println(c16.getId() + c16.getName());
        //如果get里的key不存在,就会抛异常NullPointer空指针异常
        //所以在根据key读取时,最好先判断有没有
    if(map!=null&&!map.isEmpty()){
        if(map.containsKey("c17")){
        ClassA c17 = map.get("c17");
        System.out.println(c17.getName());
        }else{
            System.out.println("不存在这个key的数据");
        }
    }
    }

再来一个例子 模拟存储最后位置

    public class Point {
        //纬度41.8
        private double lat;
        //经度123.4
        private double lon;
        public Point(double lat, double lon) {
            super();
            this.lat = lat;
            this.lon = lon;
        }
    
        public double getLat() {
            return lat;
        }
    
        public void setLat(double lat) {
            this.lat = lat;
        }
    
        public double getLon() {
            return lon;
        }
    
        public void setLon(double lon) {
            this.lon = lon;
        }
    
    }

// 1)创建:构造方法指定初始化个数或不指定初始化次数 new HashMap()--默认是初始化10 new HashMap(8) --掌握
// 2)添加: 单个添加put(key,value) --掌握
// 批量添加:putAll(Map t)
// 3)修改: 单个put(key,value) 批量:putAll(Map t) 相同key的覆盖原有的。

// 4)删除: clear() --删除所有
// remove(key) --删除指定key的一条数据
// 5)查询单个:get(key) 利用key取出value --掌握
// containsKey(key)是否存在指定key --掌握
// containsValue(value) 是否存在指定value ---了解
// 查询所有:size()-一共几条
// isEmpty()是否为空
// keyset-有哪些key ---难 了解
// entryset-(key,value) ---难 了解
@Test
public void test03() {
    // 根据手机号码,查询最后位置
    // step1 建立一个point实体
    // 沈阳的经纬度lon= 123.4 lat=41.8
    // step2 建一个map用于存放手机号及该手机号的最后位置
    // map<手机号,最后位置>
    Map lastPosMap = new HashMap();
    // step3 向map里放每个人的最后位置
    Point p1 = new Point(41.8, 123.4);
    lastPosMap.put("13904001139", p1);
    // 一口气写法
    lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
    lastPosMap.put("13840191051", new Point(41.9, 123.445));
    // 假设这个人动了,就再上报一次位置
    lastPosMap.put("13840191050", new Point(40.92, 123.423));// 王哥 131行的被覆盖
    // 查询指定手机号的最后位置
    // 能不能孙宇的最后位置
    if (lastPosMap.containsKey("18695876927")) {// 是否存在18695876927的最后位置信息呢
        System.out.println("有孙宇的最后位置");
    } else {
        System.out.println("对不起,没查到");
    }
    if (lastPosMap.containsKey("13840191050")) {// 是否存在18695876927的最后位置信息呢
        // 如果可以查到,我就可以通过get(key)方法把王浩丞的最后位置拿到。在地图上描画
        Point wanglast = lastPosMap.get("13840191050");
        // 打印一下位置里的详细信息
        System.out.println("王浩丞的位置信息" + wanglast.getLat() + " " + wanglast.getLon());
    }
    // 上面的方法比较常用 必须熟练掌握的
    // 接下来的方法 练习

}

// 以下这些不常用 了解
@Test
public void test04() {
    // 4)删除: clear() --删除所有--比较常用 delete 不带条件
    Map lastPosMap = new HashMap();
    // step3 向map里放每个人的最后位置
    Point p1 = new Point(41.8, 123.4);
    lastPosMap.put("13904001139", p1);
    // 一口气写法
    lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
    lastPosMap.put("13840191051", new Point(41.9, 123.445));
    //lastPosMap.clear();
    //System.out.println("删除数据后的map"+lastPosMap);
    // remove(key) --删除指定key的一条数据 --比较常用
    //lastPosMap.remove("13904001139");//delete from 表名 where key=?
    //System.out.println("删除数据后的map"+lastPosMap);
    // 5)查询单个:
    // containsValue(value) 是否存在指定value ---了解即可    不常用
    //Point p1 = new Point(41.8, 123.4);
    //lastPosMap.put("13904001139", p1);
    Point p4 = new Point(41.8, 123.4);
    lastPosMap.put("13904001139", p4);
    if(lastPosMap.containsValue(p1)){//true/false
        System.out.println("存在");
    }else{
        System.out.println("不存在");
    }
    // 查询所有:size()-一共几条--比较常用
    System.out.println("map里有几条数据:"+lastPosMap.size());
    // isEmpty()是否为空
    if(lastPosMap.isEmpty()){
        System.out.println("为空");
    }else{
        System.out.println("不为空");
    }
}

map循环

第一种:循环keySet,然后通过key读取value

  @Test
public void test05() {
    // keyset-有哪些key ---难了解
    // entryset-(key,value) ---难    优先掌握
    Map lastPosMap = new HashMap();
    // step3 向map里放每个人的最后位置
    Point p1 = new Point(41.8, 123.4);
    lastPosMap.put("13904001139", p1);
    // 一口气写法
    lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
    lastPosMap.put("13840191051", new Point(41.9, 123.445));
    //查询所有,有两种方式keyset
    //step1 
    Set  keys=lastPosMap.keySet();//所在key的集合
    //用加强for,循环到每个key
    for(String name:keys){
        System.out.println(name);
        //step2 用key获取value
        Point p=lastPosMap.get(name);
        System.out.println(p.getLat()+" "+p.getLon());
    }
}
// entryset-(key,value) ---难    优先掌握
@Test
public void test06() {
    // keyset-有哪些key ---难了解
    // entryset-(key,value) ---难    优先掌握
    Map lastPosMap = new HashMap();
    // step3 向map里放每个人的最后位置
    Point p1 = new Point(41.8, 123.4);
    lastPosMap.put("13904001139", p1);
    // 一口气写法
    lastPosMap.put("13840191050", new Point(40.9, 123.42));// 王哥
    lastPosMap.put("13840191051", new Point(41.9, 123.445));
    //通过循环entryset来获取entry(key,value)
    Set> s=lastPosMap.entrySet();
    //循环entry实体,就可以拿到key value
    for(Entry p:s){
        String phone=p.getKey();
        Point lp=p.getValue();
        System.out.println(lp.getLat()+" " +lp.getLon());
    }
}

treeMap key顺序 字母a-Z 数学按大学排序

@Test
public void test08() {
    Map lastPosMap = new TreeMap();
    // step3 向map里放每个人的最后位置
    Point p1 = new Point(41.8, 123.4);
    lastPosMap.put(140, p1);
    lastPosMap.put(139, new Point(41.9, 123.445));
    // 一口气写法
    lastPosMap.put(150, new Point(40.9, 123.42));// 王哥
    
    //通过循环entryset来获取entry(key,value)
    Set> s=lastPosMap.entrySet();
    //循环entry实体,就可以拿到key value
    for(Entry p:s){
        Integer phone=p.getKey();
        Point lp=p.getValue();
        System.out.println(phone+" "+lp.getLat()+" " +lp.getLon());
    }
}

作业:

    /**
    * 1、请使用LinkedList来模拟一个队列(先进先出的特性): [必做题] 
    * 1.1 拥有放入对象的方法void put(Object o) 
    * 1.2 取出对象的方法Object get() 
    * 1.3 判断队列当中是否为空的方法boolean isEmpty();
    * 并且,编写测试代码,验证你的队列是否正确。
    */
    public class MyQueue {
        //类级别定义一个LinkedList类型的变量
        LinkedList queue=new LinkedList();
        
        public void put(Object o){
            queue.addFirst(o);
        }
        public Object get(){
            Object obj=queue.getLast();
            queue.removeLast();
            return obj;
        }
        
        public boolean isEmpty(){
            return queue.isEmpty();
        }
        
        public static void main(String[] args) {
            MyQueue mq=new MyQueue();
            mq.put("hello1");
            mq.put("hello2");
            mq.put("hello3");
            
            while(!mq.isEmpty()){
                Object o=mq.get();
                System.out.println(o);
            }
        }
        
    }

2、产生10个1-100的随机数,并放到一个数组中, 把数组中大于等于10的数字放到一个list集合中,并打印到控制台
3、双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。
红色球号码从1―33中选择;蓝色球号码从1―16中选择;请随机生成一注双色球号码。
(要求同色号码不重复)

你可能感兴趣的:(第十章 集合(8))