Java笔记(8)-泛型与集合框架



  • 泛型与集合框架

    • 泛型

      • 泛型类
      • 泛型类声明对象
        • 示例
      • 泛型接口
        • 示例
      • 泛型的目的
    • 链表
      • LinkedList E 泛型类
      • 常用方法
      • 遍历链表
        • 示例
      • 排序和查找
        • 示例
      • 洗牌和旋转
    • 堆栈
      • 示例
    • 散列映射
      • HashMap KV 泛型类
      • 常用方法
      • 遍历散列映射
      • 基于散列映射的查询
        • 示例
    • 树集
      • TreeSetE泛型类
      • 节点的大小关系
      • TreeSet类常用方法
      • 示例
    • 树映射

泛型与集合框架

组织数据之结构及相关操作。

泛型

泛型(Generics)是在JDK1.5中推出的,其主要目的是可以建立具有类型安全的集合框架,如链表、散列映射等数据结构。

泛型类

ShowObject是泛型类的名称,E 是其中的泛型,可以是任何对象和接口,但不能是基本类型数据。

class ShowObject<E>

能显示对象基本信息的ShowObject类

public class ShowObject<E> {
    public void showMess(E b) {
        String mess = b.toString();// 泛型变量只能调用toString()方法
        System.out.println(mess);
    }
}

泛型类声明对象

示例

package com.泛型;

class Dog {
    public String toString() {
        return "一条小狗";
    }
}

class Cat {

     public String toString() {
         return "一只小猫";

    }

}

class ShowObject<E> {
    public void showMess(E b) {
        String mess = b.toString();// 泛型变量只能调用toString()方法
        System.out.println(mess);
    }
}

public class Main<E> {
    public static void main(String[] args) {
        ShowObject<Dog> showDog = new ShowObject<Dog>();
        showDog.showMess(new Dog());
        ShowObject<Cat> showCat = new ShowObject<Cat>();
        showCat.showMess(new Cat());

    }
}
一条小狗
一只小猫

泛型接口

"interface 名称<泛型列表>" 声明一个接口,这样声明的接口称作泛型接口。

 interface Listen<E> {
  void listen(E x);
}

示例

package com.泛型接口;

interface Listen<E> {
    void listen(E x);
}

class Student implements Listen<Piano> {

    @Override
    public void listen(Piano p) {
        p.play();
    }
}

class Teacher implements Listen<Violin> {

    @Override
    public void listen(Violin v) {
        v.play();
    }

}

class Piano {
    public void play() {
        System.out.println("钢琴协奏曲:黄河");
    }
}

class Violin {
    public void play() {
        System.out.println("小提琴协奏曲:梁祝");
    }
}

public class MyInterface {
    public static void main(String[] args) {
        Student zhang = new Student();
        System.out.println("学生听:");
        zhang.listen(new Piano());
        Teacher teacher = new Teacher();
        System.out.println("老师听:");
        teacher.listen(new Violin());
    }
}
学生听:
钢琴协奏曲:黄河
老师听:
小提琴协奏曲:梁祝

泛型的目的

Java泛型的主要目的是可以建立具有类型安全的数据结构,如链表、散列表等数据结构,最重要的一个优点就是:在使用这些泛型类建立数据结构时,不必进行强制类型转换,即不要求进行运行时的类型检查。JDK1.5是支持泛型的编译器,它将运行时的类型检查提前到编译时执行,是代码更安全。

链表

处理一些类型相同的数据,习惯使用数组这种数据结构,但使用前必须定义数组大小,且不容易改变数组的大小,因为数组改变大小意味着放弃原有的全部单元。分配太多单元又会浪费宝贵的内存资源。动态增加或减少数据项时,可以使用链表这种数据结构。

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

LinkedList < E >泛型类

java.util 包中的LinkedList<E>泛型类创建的对象以链表结构存储数据,习惯上称LinkedList类创建的对象为链表对象。

LinkedList<String> list = new LinkedList<String>

创建了一个空双链表。

常用方法

LinkedList<E>是实现了泛型接口List<E>的泛型类,而泛型接口List<E>又是Collection<E>泛型接口的子接口。LinkedList<E>泛型类的绝大部分方法都是泛型接口方法的实现。编程时,可以使用接口回调技术,即把LinkedList<E>对象的引用赋值给Collection<E>接口变量或List<E>接口变量,那么接口变量就可以调用类实现的方法。

public boolean add(E element) 向链表末尾添加一个新节点,element为数据
public int size() 返回链表的长度,即节点的个数
.
.
.

遍历链表

  • 链表对象可以使用iterator()方法获取一个Iterator对象,该对象就是针对当前链表的迭代器。
  • get(int index)方法遍历

示例

package com.链表;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class MyLinkedList {
    public static void main(String[] args) {
        List<String> list = new LinkedList<String>();//接口回调 向上转型
        list.add("大家好");
        list.add("新生26号汇报表演");
        list.add("十一快乐");
        Iterator<String> iter = list.iterator();
        while(iter.hasNext()){
            String te = iter.next();
            System.out.print(te+" ");
        }
        System.out.println("");
        for(int i=0;i<list.size();i++){
            String te = list.get(i);
            System.out.print(te+" ");
        }
    }
}
大家好 新生26号汇报表演 十一快乐
大家好 新生26号汇报表演 十一快乐 

Java提供了顺序结构的动态数组表类ArrayList,数组表采用顺序结构来存储数据。数组表不适合动态地改变它存储的数据,如增加、删除单元等(比链表慢),但是数组表获取第n个单元中的数据的速度要比链表快。ArrayList类的很多方法与LinkedList类似,二者的本质区别就是:一个使用顺序结构,一个使用链表结构。

排序和查找

要对链表按某种大小关系排序,以便查找一个数据是否和链表某个节点上的数据相等。

如果链表实现了Comparable接口的类的实例,如String对象(String实现了该接口)就可以使用Collections类调用sort(List<E> list>)方法可以对参数指定的列表排序,即按节点中存储的对象的大小升序排列节点。

Collections.sort(listString);// 按字典序排序

自定义的类可以实现泛型接口Comparable<E>中的compareTo(E b)方法来指定该类的示例相互比较大小关系的准则

a.compareTo(b)<0 称a小于b
a.compareTo(b)>0 称a大于b
a.compareTo(b)=0 称a等于b

自定义People类

class People implements Comparable<People> {
    int height, weight;

    public People(int h, int w) {
        height = h;
        weight = w;
    }
    //指定该类的示例相互比较大小关系的准则
    @Override
    public int compareTo(People o) {
        return (this.height - o.height);
    }
}

查找链表中是否含有和指定数据相对的数据,那么首先对链表排序,然后使用

public static int binarySrarch(List<T> list, T key)  查找链表中是否含有和数据key相等的数据

示例

package com.排序和查找;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

class People implements Comparable<People> {
    int height, weight;

    public People(int h, int w) {
        height = h;
        weight = w;
    }
    //指定该类的示例相互比较大小关系的准则
    @Override
    public int compareTo(People o) {
        return (this.height - o.height);
    }
}

public class Main {
    public static void main(String[] args) {
        LinkedList<String> listString = new LinkedList<String>();
        listString.add("bird");
        listString.add("apple");
        listString.add("cat");
        Collections.sort(listString);// 按字典序排序
        Iterator<String> iterString = listString.iterator();
        while (iterString.hasNext()) {// 遍历数据显示
            String s = iterString.next();
            System.out.print(s + " ");
        }

        int index = Collections.binarySearch(listString, "apple");// 查找相同
        //System.out.println(index);
        if (index >= 0) {
            System.out.println("链表中含有和对象apple相等的数据");
        }
        List<People> listPeople = new LinkedList<People>();
        listPeople.add(new People(185, 72));
        listPeople.add(new People(170, 71));
        listPeople.add(new People(172, 56));
        listPeople.add(new People(187, 82));
        Collections.sort(listPeople);
        Iterator<People> iterPeople = listPeople.iterator();
        while (iterPeople.hasNext()) {
            People p = iterPeople.next();
            System.out.println("身高:" + p.height + "cm 体重:" + p.weight);
        }
        People zhang = new People(170, 100);
        index = Collections.binarySearch(listPeople, zhang);// 查找相同
        //System.out.println(index);
        if (index >= 0) {
            System.out.println("链表中含有和对象zhang相等的数据");
        }
    }
}
    apple bird cat 链表中含有和对象apple相等的数据
    身高:170cm 体重:71
    身高:172cm 体重:56
    身高:185cm 体重:72
    身高:187cm 体重:82
    链表中含有和对象zhang相等的数据

洗牌和旋转

public static void shuffle(List<E> list) 随机排列list中的节点

static void rotate(List<E> list,int distance) 旋转链表中的节点 list为i的节点中的数据将是调用该方法前索引为i-distance) mod list.size()的节点中的数据。

public static void reverse(List<E> list) 翻转list中的数据

a b c d e 调用Collections.rotate(list,1) 之后 e b c d a,distance正值时,右转,负值,左转。

堆栈

堆栈是一种“后进先出”的数据结构,只能在一端进行输入和输出数据的操作。

使用java.util 包中的SStack<E>泛型类创建一个堆栈对象

public E push(E item)  压栈

public E pop() 出栈

public boolean empty() 判断是否有数据,有false,无true

public E peek() 获取栈顶端的数据,不能删除该数据

public int search (Object data) 获取数据在堆栈中的位置,最顶段为1,向下依次增加,不含此数据返回-1

示例

package com.堆栈;

import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(new Integer(1));// first
        stack.push(new Integer(1));// second
        int k = 1;
        while (k <= 10) {
            for (int i = 1; i <= 2; i++) {
                Integer F1 = stack.pop();// second 后进向出
                int f1 = F1.intValue();
                Integer F2 = stack.pop();
                int f2 = F2.intValue();
                // System.out.println("F2:"+f2);
                Integer temp = new Integer(f1 + f2);
                System.out.println("" + temp.toString());

                stack.push(temp);
                stack.push(F2);
                k++;
            }
        }
    }
}
2
3
5
8
13
21
34
55
89
144

散列映射

HashMap <K,V >泛型类

HashMap<K,V>是实现了泛型接口Map<K,V>的泛型类,HashMap<K,V>泛型类的绝大部分方法都是Map<K,V>接口方法的实现。编程时,可以使用接口回调技术,即把HashMap<K,V>对象的引用赋值给Map<K,V>接口变量,那么接口变量就可以调用类实现的方法。

HashMap<K,V>对象采用散列表这种数据结构存储数据,习惯上称HashMap<K,V>对象为散列映射。

  • 散列映射存储“键/值”对
  • 自动增加容量
  • 数组表和链表这两种结果,由于查找元素时不知道特定元素确定的位置,需要从头开始查找,最好用散列映射存储要查找的数据,散列映射可以减少查找的开销。
HashMap<String,Student> hashtable = new HashMap<String,Student>();

hashtable.put(K key,V value)//添加数据

常用方法

 public void clear() 清空散列映射
 public Object clone() 返回当前散列映射的一个克隆
 public int size() 返回散列映射的大小,即散列映射的键值对的个数
  .
  .

遍历散列映射

public Collection<V> values()方法返回一个实现Collection<V>接口类创建的对象,可以使用接口回调技术,即将该对象的引用给Collection<V>接口变量,该变量可以回调iterator()方法获取一个Iterator对象,这个Iterator对象存放着散列映射中所有的”键值”对中的值。

<todo>

Scanner类读取

package com.散列映射;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class TestCollection {
    public static void main(String[] args) {
        File file = new File("word.txt");
        try {
            Scanner sc = new Scanner(file);
            while (sc.hasNextLine()) { // 以空格作为分隔符
                String englishWord = sc.next();
                String chineseWord = sc.next();
                System.out.println(englishWord+" "+chineseWord);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
mountain 山
water 水
canvas 画
fish 鱼
dog 狗
vehicle 车辆
decay 腐败

基于散列映射的查询

示例

word.txt

mountain 山 water 水 canvas 画
fish 鱼 dog 狗 vehicle 车辆 decay 腐败
package com.散列映射;

import java.io.File;
import java.util.HashMap;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        HashMap<String, String> hashtable;
        File file = new File("word.txt");
        ReadWord read = new ReadWord();
        hashtable = new HashMap<String, String>();
        read.putWordToHashMap(hashtable, file); // 读取word.txt里的数据,存到HashMap中
        Scanner scanner = new Scanner(System.in);// 键盘输入
        System.out.println("输入要查询的英文单词:");
        while (scanner.hasNext()) { // scanner.hasNextLine()
            String englishWord = scanner.nextLine();
            /**
             * 获取键盘输入字符串 存到englishWord next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符
             * 获取不到空格 而nextLine()方法的结束符只是Enter键
             */
            if (englishWord.length() == 0)
                break;
            if (hashtable.containsKey(englishWord)) {
                String chineseWord = hashtable.get(englishWord);
                System.out.println(chineseWord);
            } else {
                System.out.println("没有此单词");
            }
            System.out.println("输入要查询的英文单词:");
        }
    }
}

class ReadWord {
    public void putWordToHashMap(HashMap<String, String> hashtable, File file) {
        try {
            Scanner sc = new Scanner(file);
            while (sc.hasNext()) { // 以空格作为分隔符
                String englishWord = sc.next();
                String chineseWord = sc.next();
                hashtable.put(englishWord, chineseWord);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}
输入要查询的英文单词:
dog
狗
输入要查询的英文单词:
cat
没有此单词
输入要查询的英文单词:
mountain
山
输入要查询的英文单词:

树集

TreeSet<E>泛型类

TreeSet<E>类是实现Set<E>接口的类,它的大部分实现方法都是接口方法的实现。TreeSet<E>类创建的对象称作树集。树集采用树结构存储数据,树节点的数据会按存放的数据的“大小”顺序一层一层地依次排列,同层中从左到右从小到大递增排列,下一层的都比上一层小

TreeSet<String> mytree = new TreeSet<String>();
mytree.add("boy");

节点的大小关系

树集节点的排列和链表不同,不按添加的先后顺序排列。树集用add方法添加节点,节点会按其存放的数据的”大小“ 顺序一层一层地依次排列。

自定义的类,这里使用了Comparable<E>泛型接口中compareTo(E b)方法来比较大小

TreeSet类常用方法

    public boolean add(E o) 向树集添加节点,成功true
    public void clear() 删除树集中的所有节点
    public E first() 返回树集中第一个节点的数据(最小的节点)
    public boolean remove(Object o) 删除树集中的存储参数指定的对象的最小节点,成功true
    .
    .

示例

package com.树集;

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

public class MyTreeSet {
    public static void main(String[] args) {
        TreeSet<Student> mytree = new TreeSet<>();
        Student st1, st2, st3;
        st1 = new Student(178, "老霍");
        st2 = new Student(176, "胖子");
        st3 = new Student(158, "羊祯");
        mytree.add(st1);
        mytree.add(st2);
        mytree.add(st3);
        Iterator<Student> te = mytree.iterator();// 迭代器
        while (te.hasNext()) {
            Student stu = te.next();
            System.out.println("" + stu.name + " " + stu.height + " cm");// 按身高从矮到高
        }
    }
}
羊祯 158 cm
胖子 176 cm
老霍 178 cm

树映射

TreeMap<K,V>类实现了Map<K,V>接口,称TreeMap<K,V>对象为树映射。

public V put(K key,V value) //添加节点

树映射的节点存储”关键字/值“对,树映射保证节点是按照节点中的关键字升序排列的。

48 类库 类 集框架中常见类的使用方法(ArrayList,LinkedList,Queue,Stack,HashSet,HashMap))

50 数据库关系型数据库的基本概念

51 SQL 分类

52 DDL,DML,查询

时间: 2024-10-09 10:13:06

Java笔记(8)-泛型与集合框架的相关文章

ACCP8.0 java课程第二学期-关于集合框架

本章重点 掌握ArrayList LinkedList HashMap与泛型集合 本章难点 泛型的理解 一 关于集合1)如果写程序时不知道运行时需要多少对象,或者需要更复杂的方式存储对象时,考虑使用集合它位于java.util包下2)集合框架包含接口,实现类,和相关算法3)Collection接口存储一组不唯一,无序的对象4)Set接口继承Collection接口,存储一组唯一无序的对象5)List接口继承Collection接口,存储一组不唯一有序的对象6)Map接口存储一组键值对的对象,ke

Java复习第三天---集合框架的相关知识

集合框架总览: Collection 接口常用方法 //1.add()向集合中添加数据 c.add(apple01); c.add(apple02); c.add(apple03); c.add(apple04); c.add(apple05); //2.isEmepty()检测当前集合是否为空 boolean empty = c.isEmpty(); System.out.println("is empty:"+empty); //3.size()返回当前集合的长度 int size

Java基础---泛型、集合框架工具类:collections和Arrays

第一讲     泛型(Generic) 一.概述 1.JDK1.5版本以后出现的新特性.用于解决安全问题,是一个类型安全机制. 2.JDK1.5的集合类希望在定义集合时,明确表明你要向集合中装入那种类型的数据,无法加入指定类型以外的数据. 3.泛型是提供给javac编译器使用的可以限定集合中的输入类型说明的集合时,会去掉“类型”信息,使程序运行效率不受影响,对参数化的泛型类型,getClass()方法的返回值和原始类型完全一样. 4.由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就

Java基础知识强化之集合框架笔记07:Collection集合的遍历之迭代器遍历

1. Collection的迭代器: 1 Iterator iterator():迭代器,集合的专用遍历方式 2. 代码示例: package cn.itcast_03; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /* * Iterator iterator():迭代器,集合的专用遍历方式 * Iterator(迭代器): * Object next():获取元素,并移动

Java基础知识强化之集合框架笔记31:集合之泛型类的概述和基本使用

1. 为什么会有泛型呢? (1)早期的Object类型可以接收任意的对象类型,但是在实际使用中,会有类型转换的问题,也存在这隐患,所以Java提供了泛型来解决这个安全问题. 2. 泛型类的使用: (1)首先定义一个泛型类ObjectTool,如下: 1 package cn.itcast_04; 2 3 /* 4 * 泛型类:把泛型定义在类上 5 */ 6 public class ObjectTool<T> { 7 private T obj; 8 9 public T getObj() {

黑马程序员之——Map、泛型、集合框架工具类:Collections,Arrays

第一讲,第二讲:黑马程序员_毕向东_Java基础视频教程第15天-06-集合框架(泛型概述),(泛型使用) 一,泛型了解: 泛型的由来:泛型是JDK1.5版本以后出现的新特性.用于解决安全问题,是一个类型安全机制. 好处:将运行时期出现的问题ClassCastException,转移到了编译时期.方便于程序员解决问题.让运行时期问题减少.安全. 好处:避免了强制转换的麻烦. 二,泛型的格式:通过<>来定义要操作的引用数据类型.    如:ArrayList<String>  //定

Java基础知识强化之集合框架笔记30:集合之泛型概述和基本使用

1. 泛型的引入: (1)首先我们看看下面这一段代码,如下: 1 package cn.itcast_01; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 7 public class GenericDemo { 8 public static void main(String[] args) { 9 // 创建 10 ArrayList<String> array = new ArrayList<Str

Java基础知识强化之集合框架笔记03:Collection集合的功能概述

1. Collection功能概述:Collection是集合的顶层接口,它子体系有重复的,有唯一性,有有序的,无序的. (1)添加功能 1 boolean add(Object obj):添加一个元素 2 boolean addAll(Collection c):添加一个集合的元素 (2)删除功能 1 void clear():移除所有元素 (3)判断功能 1 boolean contains(Object obj):判断集合中是否包含指定的元素 2 boolean containsAll(C

Java中泛型在集合框架中的应用

泛型是Java中的一个重要概念,上一篇文章我们说过,当元素存入集合时,集合会将元素转换为Object类型存储,当取出时也是按照Object取出的,所以用get方法取出时,我们会进行强制类型转换,并且通过代码也可以看出来,我们放入其他类型时,如字符串,编译器不会报错,但是运行程序时会抛出类型错误异常,这样给开发带来很多不方便,用泛型就解决了这个麻烦 泛型规定了某个集合只能存放特定类型的属性,当添加类型与规定不一致时,编译器会直接报错,可以清楚的看到错误 当我们从List中取出元素时直接取出即可,不