面向对象

常用对象API_01

1.Map集合

1.1 特点

  • 存储的是键值对
  • 必须保证键的唯一性

1.2 常用方法

1. 添加

  • value put(key,value):返回前一个和key关联的值,如果没有返回null

2. 删除

  • void clear():清空map集合
  • value remove(key):根据指定的key移除这个键值对

3. 判断

  • boolean containsKey(key)
  • boolean containsValue(value)
  • boolean isEmpty()

4. 获取

  • value get(key):通过键获取值,如果没有该键返回null;也可通过返回null来判断是否包含指定键
  • int size():获取键值对的个数

1.3 基本方法演示

public class MapDemo {

    public static void main(String[] args) {
        Map map = new HashMap();
        method(map);
    }

    public static void method(Map map) {
        // 添加元素
        System.out.println(map.put(8, "wangwu"));// null
        System.out.println(map.put(8, "lisi"));// wangwu 存相同的键,值会被覆盖

        map.put(2, "张三");
        map.put(7, "李四");

        // 删除元素
        System.out.println("移除了:" + map.remove(2));

        // 判断
        System.out.println("包含:" + map.containsKey(7));

        // 获取
        System.out.println("获取:" + map.get(8));

        System.out.println(map);
    }

}

1.4 keySet方法演示一

public class MapDemo {

    public static void main(String[] args) {
        Map map = new HashMap();
        method(map);
    }

    public static void method(Map map) {
        map.put(8, "wangwu");
        map.put(2, "zhangsan");
        map.put(6, "lisi");
        map.put(7, "zhaoliu");

        // 通过keySet方法获取map中所有的键所在的Set集合,
        // 再通过Set的迭代器获取到每一个键,再对每一个键通过map集合的get方法获取其对应的值即可

        Set keySet = map.keySet();
        Iterator it = keySet.iterator();

        while (it.hasNext()) {
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key + ":" + value);
        }
    }
}

1.5 keySet方法演示二

public class MapDemo {

    public static void main(String[] args) {
        Map map = new HashMap();
        method_3(map);

    }

    public static void method_3(Map map) {
        map.put(8, "wangwu");
        map.put(2, "zhangsan");
        map.put(6, "lisi");
        map.put(7, "zhaoliu");
        /*
         * 通过map转成set就可以迭代
         * entrySet方法将键和值的映射关系作为对象存储到了Set集合中,
         * 而这个映射关系的类型就是Map.Entry类型
         */

        Set> entrySet = map.entrySet();

        Iterator> it = entrySet.iterator();

        while(it.hasNext()){
            Map.Entry me = it.next();
            Integer key = me.getKey();
            String value = me.getValue();
            System.out.println(key+":"+value);
        }
    }
}   

1.6 values()演示

public class MapDemo {

    public static void main(String[] args) {
        Map map = new HashMap();
        method_4(map);

    }

    public static void method_4(Map map) {
        map.put(8, "wangwu");
        map.put(2, "zhangsan");
        map.put(6, "lisi");
        map.put(7, "zhaoliu");

        Collection values = map.values();

        Iterator it = values.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}   

1.7 常见子类对象

  • Hashtable:内部结构是哈希表,是同步的,不允许null作为键,null作为值

Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合

  • HashMap:内部是哈希表,不是同步的,允许null作为键,null作为值
  • TreeMap:内部结构是二叉树,不是同步的,可以对Map集合中的键进行排序

2.泛型

2.1 为什么需要泛型?

  1. 简化缩写;
  2. 提高安全性
  3. 避免强转的麻烦,提高效率
public class GenericDemo {

    public static void main(String[] args) {
        ArrayList al = new ArrayList();

        al.add("abc");// Object
        // java.lang.Integer cannot be cast to java.lang.String
        // al.add(4);// al.add(new Integer(4));

        Iterator it = al.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }

    }

}

2.2 泛型的擦除与补偿

泛型用于编译时期,确保了类型的安全;运行时,会将泛型去掉,生成的class文件中是不带泛型的,这称为泛型的擦除。

  • 为什么要擦除呢?

因为为了兼容运行的类加载器

  • 泛型的补偿: 在运行时,通过获取元素的类型进行转换动作,不用使用者再强转了

2.3 泛型在集合中的应用

/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.bean;

/**
 * Person Bean
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int compareTo(Person p) {
        int temp = this.age - p.age;
        return temp == 0 ? this.name.compareTo(p.name) : temp;
    }

}
/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.comparator;

import java.util.Comparator;

import com.hoki.bean.Person;

/**
 * 名称比较器
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class ComparatorByName implements Comparator<Person> {

    public int compare(Person o1, Person o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp == 0 ? o1.getAge() - o2.getAge() : temp;
    }
}
/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.generic;

import java.util.Iterator;
import java.util.TreeSet;

import com.hoki.bean.Person;
import com.hoki.comparator.ComparatorByName;

/**
 * 泛型示例二
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class GenericDemo2 {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new ComparatorByName());

        ts.add(new Person("lisi", 21));
        ts.add(new Person("lisi3", 23));
        ts.add(new Person("kisi", 21));
        ts.add(new Person("lis0", 20));
        ts.add(new Person("alis0", 20));

        Iterator it = ts.iterator();

        while (it.hasNext()) {
            Person p = it.next();
            System.out.println(p.getName() + ":" + p.getAge());

        }

    }

}

2.4 泛型类

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。

/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.generic.custom;


/**
 * 自定义泛型类
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class Tool<QQ> {

    private QQ q;

    public QQ getObject() {
        return q;
    }

    public void setObject(QQ obj) {
        this.q = obj;
    }

}
/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.generic.custom;

import com.hoki.bean.Person;

/**
 * 自定义泛型
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class GenericDefine {
    public static void main(String[] args) {
        Tool tool = new Tool();

        tool.setObject(new Person());
        Person p = tool.getObject();
    }
}

2.5 泛型限定

泛型的通配符是?

  • 上限
:只接受E及其E的子类对象
  • 下限
super E>:只接受E类型及其E的父类型

一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患;通常对集合中的元素进行取出操作时,可以使用下限。

3.集合查阅技巧

需要唯一?
    --需要:Set
        --需要执定顺序:
            --需要:TreeSet
            --不需要:HashSet
            --需要一个和存储一致的顺序:LinkedHashSet
    --不需要:List
        --需要频繁增删?
            --需要:LinkedList
            --不需要:ArrayList

前缀名就是该集合所属的体系,后缀名就是该集合的数据结构。

4.Map集合练习-记录字母出现次数

4.1 问题描述

对于一个字符串,记录其中每一个字母出现的次数;

要求打印结果如:a(2)b(1)…

4.2 问题分析

对于结果的分析发现,字母和次数之间存在着映射的关系,而且这种关系很多;意味着需要存储,能存储映射关系的容器有数组和Map集合;没有有序编号,可以使用Map集合;又发现可以保证唯一的一方具备顺序如a,b,c…,所以可以使用TreeMap集合。这个集合最终应该存储的是字母和次数的对应关系。

4.3 解决思路

  1. 因为操作的是字符串中的字母,所以先将字符串变成字符数组
  2. 遍历字符数组,用每一个字母作为键去查Map集合这个表;如果该字母键不存在,就将该字母作为键,1作为值存储到Map集合中;如果该字母键存在,就将该字母键对应值取出并+1,再将该字母和+1后的值存储到Map集合中,键相同的值会覆盖,这样就记录了该字母的出现次数。
  3. 遍历结束,Map集合就记录所有字母的出现的次数

4.4 代码实现

/**
 * 记录字母出现次数
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class HashMapDemo {

    public static void main(String[] args) {
        //定义一个字符串
        String s = "aaaaaabbbbcc";
        //将字符串转为字符数组
        char[] arr = s.toCharArray();
        //定义双列集合,存储字符串中字符以及字符出现的次数
        HashMap hm = new HashMap<>();
        //遍历字符数组获取每一个字符,并将字符存储到双列集合中
        for(char c:arr){
            //存储过程中要判断,如果集合中不包含这个键,就将这个字符作为键存入;否则,就将键的值++;
            /*if(!hm.containsKey(c)){
                hm.put(c, 1);
            }else{
                hm.put(c, hm.get(c)+1);
            }*/
            hm.put(c, !hm.containsKey(c)?1:hm.get(c)+1);
        }

        //打印双列集合,获取字符出现的次数
        for(Character key:hm.keySet()){
            System.out.println(key+"=="+hm.get(key));
        }
    }

}

5.HashMap和Hashtable的区别(面试题,亲身体验被面过)

HashMap Hashtable
线程不安全的 线程安全
效率高 效率低
since 1.2 since 1.0
可存储null键和null值 不可存储null键和null值
/**
 * HashMap之所以设计出来就是为了防止Hashtable遇到null键或null值时,程序中断,代码不继续运行的情况
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class HashMap2 {

    public static void main(String[] args) {
        // 可存储null键和null值
        HashMap hm = new HashMap<>();
        hm.put(null, 23);
        hm.put("hoki", 22);
        System.out.println(hm);

        // 抛出空指针异常,证明不可存储null键和null值
        Hashtable ht = new Hashtable<>();
        ht.put(null, 23);
        ht.put("hoki", null);
        System.out.println(ht);
    }

}

6.洗牌游戏

模拟斗地主洗牌和发牌,牌没有排序

6.1 分析

  1. 一个扑克集合对象将扑克牌存储进去
  2. 洗牌
  3. 发牌
  4. 看牌

6.2 代码实现

/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.doudizhu;

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

/**
 * 模拟斗地主洗牌和发牌,牌没有排序
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class Doudizhu {
    public static void main(String[] args) {
        // 1. 一个扑克集合对象将扑克牌存储进去
        String[] num = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                "J", "Q", "K" };
        String[] color = { "红桃", "黑桃", "方块", "梅花" };
        ArrayList poker = new ArrayList<>();
        // 拼接花色和数字
        for (String s1 : color) {
            for (String s2 : num) {
                poker.add(s1.concat(s2));
            }
        }
        // 添加大王和小王
        poker.add("大王");
        poker.add("小王");

        // 2. 洗牌
        Collections.shuffle(poker);
        // 3. 发牌
        ArrayList xiaoming = new ArrayList<>();
        ArrayList xiaohong = new ArrayList<>();
        ArrayList me = new ArrayList<>();
        ArrayList dipai = new ArrayList<>();

        for (int i = 0; i < poker.size(); i++) {
            if (i >= poker.size() - 3) {
                dipai.add(poker.get(i));
            } else if (i % 3 == 0) {
                xiaoming.add(poker.get(i));
            } else if (i % 3 == 1) {
                xiaohong.add(poker.get(i));
            } else {
                me.add(poker.get(i));
            }
        }

        // 4. 看牌
        System.out.println(xiaoming);
        System.out.println(xiaohong);
        System.out.println(me);
        System.out.println(dipai);

    }
}

6.3 对牌进行排序

/*
 * COPYRIGHT (C) 2018 BY HOKI SOFTWARE. ALL RIGHTS RESERVED.
 */
package com.hoki.doudizhu;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/**
 * 模拟斗地主洗牌和发牌,并对牌进行排序
 * 
 * @author Hoki_Lin
 * @since 1.0
 */
public class Doudizhu_Sort {
    public static void main(String[] args) {
        // 1. 一个扑克集合对象将扑克牌存储进去
        String[] num = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
                "K", "A", "2", };
        String[] color = { "红桃", "黑桃", "方块", "梅花" };
        HashMap hm = new HashMap<>();
        ArrayList list = new ArrayList<>();
        int index = 0;
        // 拼接扑克牌并将索引和扑克牌存储到hm中
        for (String s1 : num) {// 获取数字
            for (String s2 : color) {// 获取颜色
                list.add(index);// 将0~51添加到list集合中
                hm.put(index++, s2.concat(s1));

            }
        }

        // 将大王和小王都添加进hm中
        list.add(index);// 将52添加到list集合中
        hm.put(index++, "小王");
        list.add(index);// 将53添加到list集合中
        hm.put(index, "大王");

        // 2.洗牌
        Collections.shuffle(list);
        // System.out.println(list);

        // 3.发牌
        TreeSet xiaoming = new TreeSet<>();
        TreeSet xiaohong = new TreeSet<>();
        TreeSet me = new TreeSet<>();
        TreeSet dipai = new TreeSet<>();

        for (int i = 0; i < list.size(); i++) {
            if (i >= list.size() - 3) {
                dipai.add(list.get(i));
            } else if (i % 3 == 0) {
                xiaoming.add(list.get(i));
            } else if (i % 3 == 1) {
                xiaohong.add(list.get(i));
            } else {
                me.add(list.get(i));
            }
        }

        // 4.看牌
        showPoker(hm, xiaoming, "小明");
        showPoker(hm, xiaohong, "小红");
        showPoker(hm, me, "我");
        showPoker(hm, dipai, "底牌");
    }

    public static void showPoker(HashMap hm,
            TreeSet ts, String name) {
        System.out.print(name + "的牌是:");
        for (Integer i : ts) {
            System.out.print(hm.get(i) + " ");
        }
        System.out.println();
    }
}

7.总结

Collection
        List(存取有序,有索引,可重复)
            ArrayList
                底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
            LinkedList
                底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
            Vector
                底层是数组实现的,线程安全,无论增删查改都慢

            如果查找和修改多的话,用ArrayList
            如果增和删多的话,用LinkedList
            如果都多,用ArrayList
        Set(存取无序,无索引,不可重复)
            HashSet
                底层是哈希算法实现
                LinkedHashSet
                    底层是链表实现的,但是也是可以保证元素唯一,和HashSet原理一样
            TreeSet
                底层是二叉树算法实现的
            一般在开发中不需要对存储的元素进行排序,所以在开发的时候大多用HashSet
Map
        HashMap
            底层是哈希算法,针对键
            LinkedHashMap
                底层是链表,针对键
        TreeMap 
            底层是二叉树算法,针对键
        开发中用HashMap比较多

你可能感兴趣的:(面向对象)