黑马程序员——java-集合框架(二)

———–android培训、java培训、java学习型技术博客、期待与您交流!————

1
泛型

(1)一种把明确数据类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的数据类型。
    默认情况下,泛型指的是Object类型。

(2)泛型的格式:
    <数据类型>
如:ArrayList<String> list=new ArrayList<String>();

(3)泛型的好处:
    A:优化了程序设计,解决了黄色警告线问题。
    B:把运行时期的异常提前到了编译期间。
    C:避免了强制类型转换。

(4)泛型的弊端:
    用泛型限定了集合以后,集合中只能存储同一种数据类型。

(5)泛型在什么时候用呢?
    看API,如果看到了<>,就说明这里要使用泛型。
    一般来说,就是在集合中用。

    自己的想的:泛型的使用相当于把集合打回了原形,怎么理解?
    在集合中有了泛型的限制,集合中就只能存放同一种类型的数据,这数组又一样了。

    有意思的是这句话:在数组中存放的数据都可以存放在集合中,集合中存放的数据也都可以存放在数组中
    理解:数组中可以存放基本类型的数据,也可以存放引用类型的数据,数组中的基本类型的数据通过对应的包装类可以封装成对象,存放在集合中,所以,就可以理解上边这句话。

(6)集合的小问题:

    A:集合可以存储不同类型的元素,在遍历的时候,给出不同的判断即可。
        Object obj = it.next();
        if(obj instanceof String) {
            ...
        }else if(obj instanceof Integer) {

        }

    B:集合中存储的基本类型,其实存储的不是基本类型,而是对应的包装类类型。

(7)把以前集合的案例用泛型改进。
    ArrayList<String> array = new ArrayList<String>();

    array.add("hello");
    array.add("world");
    array.add("java");

    Iterator<String> it = array.iterator();
    while(it.hasNext()) {
        String s = it.next();
        System.out.println(s);
    }

2
增强for

(1)格式:

    for(Collection集合或者数组中的元素的数据类型 变量 : Collection集合或者数组的名称) {
        使用变量即可。这个变量其实就是集合或者数组中的元素。
    }

(2)好处:
    简化了集合或者数组的遍历


(3)把以前集合的案例用增强for改进遍历。
ArrayList array = new ArrayList();

    array.add("hello");
    array.add("world");
    array.add("java");

    for(String s : array) {
        System.out.println(s);
    }

3
泛型的扩展:

(1)泛型类
    class Demo<QQ> {
        public void show(QQ qq) {
            ...
        }
    }
package Generic;

public class GenericText
{
    public static void main(String[] args)
    {

        Persion<String> p = new Persion<String>();
        p.print("niaho");
        Persion<Boolean> p1 = new Persion<Boolean>();
        p1.print(true);

    }

}

class Persion<E>//泛型类
{

    public void print(E s)
    {
        System.out.println(s);

    }

}

(2)泛型方法
    class Demo {
        public <T> void method(T t) {
            ...
        }
    }
package Generic;

import java.lang.reflect.Method;

public class GenericMehtod
{
    public static void main(String[] args)
    {
        Student p = new Student();
        p.Method("你好");
        p.Method(10);
        p.Method(true);
        p.Method(p);

    }
}

class Student
{
    public <E> void Method(E e)
    {
        System.out.println(e);
    }
}

(3)泛型接口
    interface Inter<QQ> {
        void show(QQ qq);
    }

    //方式1--已经明确了数据类型
    class InterImpl implements Inter<String> {
        public void show(String s){

        }
    }

    //方式2--没有明确数据类型
    接口不能实例化,所以接口上的泛型需要依赖于类上的泛型,通过类上的泛型,来实例化接口上的泛型
    class InterImpl<QQ> implements Inter<QQ> {
        public void show(QQ qq){
            ...
        }
    }   

4
Set集合(接口)

   (1)HashSet   
    如何保证元素唯一性的呢?
    底层数据结构是哈希表(散列表)。具体的是由一个元素是单向链表的数组组成。
    它依赖于两个方法:hashCode()和equals()方法。
    执行顺序:
        先判断hashCode()是否相同,
            如果相同
                继承执行equals()方法,看其返回值:
                    true:元素重复,不存储。
                    false:元素不重复,存储。
            如果不同
                存储。

    记住:
        看到HashXxx结构的集合,就要知道,被该集合存储的元素要重写hashCode()和equals()方法。而且,是自动生成的。
package Set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetText
{
    public static void main(String[] args)
    {
        Set<String> s = new HashSet<String>();

        s.add("java");
        s.add("ades");
        s.add("hello");
        s.add("java");
        s.add("ades");

        // 增强for循环遍历集合
        for (String e : s)
        {
            System.out.println(e);
        }

        // 使用迭代器进行遍历
        Iterator it = s.iterator();
        while (it.hasNext())
        {
            System.out.println(it.next());
        }
    }

}

(2)TreeSet

    底层数据结构是二叉树。
    在TreeSet集合中存放Integer类型的数据时排序是按照二叉树的中根遍历排序的
    补充知识点:
    二叉树的排序方法:
    A:先根遍历
    B:中根遍历
    C:后根遍历


    如何保证元素的唯一性的呢?
        根据比较的返回值是否是0来决定。
    如何保证元素的排序的呢?
        A:自然排序 元素具备比较性
            让集合中被存储的元素所属的类实现Comparable接口。
        B:比较器排序 集合具备比较性
            在创建集合对象的时候,让构造方法接收一个Comparator接口的子类对象。

—–使用不带参数的构造方法:按照默认的自然顺序排序

package Set;

import java.util.Comparator;
import java.util.TreeSet;

import javax.management.loading.PrivateClassLoader;

public class TreeSetText
{
    public static void main(String[] args)
    {
        Man m1 = new Man("zhans1", 20);
        Man m2 = new Man("zhans2", 21);
        Man m3 = new Man("zhanhua1", 22);
        Man m4 = new Man("zhanhan2", 22);
        Man m5 = new Man("zhansan", 20);
        Man m6 = new Man("zhansan", 21);

        TreeSet<Man> ts = new TreeSet<Man>();

        ts.add(m1);
        ts.add(m2);
        ts.add(m3);
        ts.add(m4);
        ts.add(m5);
        ts.add(m6);

        for (Man m : ts)
        {
            System.out.println(m);
        }

    }

}

class Man implements Comparable<Man>
{
    private String name;
    private int age;

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

    @Override
    public String toString()
    {
        return "Man [name=" + name + ", age=" + age + "]";
    }

    @Override
    public int compareTo(Man o)
    {
        int num1 = this.name.length() - o.name.length();
        int num2 = num1 == 0 ? this.name.compareTo(o.name) : num1;
        int num3 = num2 == 0 ? this.age - o.age : num2;
        return num3;

    }

}

—–使用带参数的构造方法:并按照指定的顺序排序

package Set;

import java.util.Comparator;
import java.util.TreeSet;

import javax.management.loading.PrivateClassLoader;

public class TreeSetText
{
    public static void main(String[] args)
    {
        Man m1=new Man("zhans1",20);
        Man m2=new Man("zhans2",21);
        Man m3=new Man("zhanhua1",22);
        Man m4=new Man("zhanhan2",22);
        Man m5=new Man("zhansan",20);
        Man m6=new Man("zhansan",21);
        //使用的匿名内部类,用的是Comparator的子类对象
        TreeSet<Man> ts=new TreeSet<Man>(new Comparator<Man>()
        {

            @Override//重写这个方法,实现排序,并保证元素的唯一性
            public int compare(Man o1, Man o2)
            {
                int num1=o1.getName().length()-o2.getName().length();
                int num2=num1==0? o1.getName().compareTo(o2.getName()):num1;
                int num3=num2==0? o1.getAge()-o2.getAge():num2;
                return num3;
            }

        });
        ts.add(m1);
        ts.add(m2);
        ts.add(m3);
        ts.add(m4);
        ts.add(m5);
        ts.add(m6);

        for(Man m:ts)
        {
            System.out.println(m);
        }


    }

}

class Man 
{
    private String  name;
    private int age;

    public Man(String name,int age)
    {
        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;
    }



    @Override
    public String toString()
    {
        return "Man [name=" + name + ", age=" + age + "]";
    }



}

(3)LinkedHashSet
    底层由链表和哈希表组成。
    由链表保证有序。
    由哈希表保证唯一。

5
介绍一个数组的工具类:
类 Arrays:
此类包含用来操作数组(比如排序和搜索)的各种方法
方法:
public static List asList(T… a)
把数组转集合

package Set;

import java.util.Arrays;
import java.util.List;

public class asListText
{
    public static void main(String[] args)
    {
        String[] strings =new String[]{"袁郎","郎平","许三多","大傻","狗蛋"};

        List arrayList =Arrays.asList(strings);
        //arrayList.add("小娟");改变了长度,报错
        //arrayList.remove(0);改变了长度,报错
        arrayList.set(3, "中泰");//长度不变,不会报错

        System.out.println(arrayList);
    }

//值得注意的是:把数组转集合后,对集合的操作不能改变集合中元素的个数
}

6
Map集合(接口)

 (1) 集合中的泛型不能使基础类型的,只能是基础类型的包装类型和引用类型

  (2) Map集合存储是键值对形式的元素。

   (3)Map和Collection集合的区别(面试题)
    A:Map集合存储的是键值对形式的元素。
      Collection集合存储的是单个的元素。
    B:Map集合的键是唯一的。
      Collection的儿子Set集合元素是唯一的。
    C:Map集合的值是可以重复的。
      Collection的儿子List集合的元素是可以重复的。

(4)Map集合的功能概述:

    A:添加功能
    V put(K key,V value):如果键不存在,就是添加功能。如果键存在,就是修改功能。返回的是被修改前的值。

    B:删除功能
    void clear():清空集合中的所有键值对元素。
    V remove(Object key):根据键删除键值对元素,并把值返回。

    C:判断功能
    boolean containsKey(Object key):判断集合中是否包含指定的键。
    boolean containsValue(Object value):判断集合中是否包含指定的值。
    boolean isEmpty():判断集合是否为空。

    D:获取功能
    Set<Map.Entry<K,V>> entrySet():
    V get(Object key):根据键去集合中获取值。
    Set<K> keySet():返回的是集合中所有键的元素。
    Collection<V> values():返回的是集合中所有值的元素。


    E:长度功能
    int size():集合中的键值对元素的对数。

Map集合的遍历:

    A:通过键找值
        a:获取所有键的集合。Map集合的keySet()方法
        b:遍历键的集合,得到每一个键。增强for。
        c:根据键去map集合中找值。Map集合的get(K key)方法。

    B:通过键值对对象找键和值



        a:获取所有键值对对象的集合。先调用Map集合的Set<Map.Entry<K,V>> entrySet()方法。
        b:遍历键值对对象的集合,得到每一个键值对对象。增强for。
        c:根据键值对对象获取键和值。调用Map.Entry<>类型元素的getKey()方法和getValue()方法。
        一定注意,getKey()方法和getValue()方法不是Map集合中的而是Map.Entry<>中的

对Map集合的遍历:

package Set;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapText
{
    public static void main(String[] args)
    {
        // 创建集合对象
        Map<Integer, String> map = new HashMap<Integer, String>();
        // 添加元素
        map.put(1, "袁郎");
        map.put(2, "郎平");
        map.put(3, "平袁");
        map.put(4, "袁崇焕");
        // 第一种遍历的方法:(通过的到key的集合,来遍历)
        // 遍历map集合:步骤
        /*
         * A:首先得到key的集合 ---map.keySet();B:遍历Key的集合。---map.get(Key);
         * 通过key找到相应的Values
         */
        Set<Integer> set = map.keySet();

        for (Integer key : set)
        {
            System.out.println(key + "------" + map.get(key));
        }

        // 第二中遍历方法:(通过拿到这个集合的对象,通过这个对象,得到对应的key和Value)

        Set<Map.Entry<Integer, String>> set2 = map.entrySet();

        for (Map.Entry<Integer, String> m : set2)
        {
            System.out.println(m.getKey() + "-------
 + m.getValue());
        }

    }



对Map集合两种遍历方法的图示:
这里写图片描述
7

   Hashtable和HashMap的区别?(面试题)
    A:HashMap 线程不安全,效率高。允许null键和null值。
    B:Hashtable 线程安全,效率低。不允许null键和null值。

8
集合框架的继承图示:
这里写图片描述

———–android培训、java培训、java学习型技术博客、期待与您交流!————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值