Java笔记(8)-泛型、链表、LinkedList<E>、Iterator迭代器、Collections类方法、堆栈、HashMap<K,V>、TreeSet<E>、自动装箱和拆箱
来源:互联网 发布:机械优化设计方法 pdf 编辑:程序博客网 时间:2024/06/03 20:13
热爱生命
—汪国真
我不去想是否能够成功
既然选择了远方
便只顾风雨兼程
我不去想能否赢得爱情
既然钟情于玫瑰
就勇敢地吐露真诚
我不去想身后会不会袭来寒风冷雨
既然目标是地平线
留给世界的只能是背影
我不去想未来是平坦还是泥泞
只要热爱生命
一切,都在意料之中
泛型与集合框架
组织数据之结构及相关操作。
1 泛型
泛型(Generics)是在JDK1.5中推出的,其主要目的是可以建立具有类型安全的集合框架,如链表、散列映射等数据结构。
1.1 泛型类
ShowObject是泛型类的名称,E 是其中的泛型,可以是任何对象和接口,但不能是基本类型数据。
class ShowObject<E>
能显示对象基本信息的ShowObject类
public class ShowObject<E> { public void showMess(E b) { String mess = b.toString();// 泛型变量只能调用toString()方法 System.out.println(mess); }}
1.2 泛型类声明对象
示例
Main.java
//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();// 泛型变量只能调用Object类中的方法 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()); }}
一条小狗一只小猫
1.3 泛型接口
"interface 名称<泛型列表>"
声明一个接口,这样声明的接口称作泛型接口。
interface Listen<E> { void listen(E x);}
示例
MyInterface.java
//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()); }}
学生听:钢琴协奏曲:黄河老师听:小提琴协奏曲:梁祝
1.4 泛型的目的
Java泛型的主要目的是可以建立具有类型安全的数据结构,如链表、散列表等数据结构,最重要的一个优点就是:在使用这些泛型类建立数据结构时,不必进行强制类型转换,即不要求进行运行时的类型检查。JDK1.5是支持泛型的编译器,它将运行时的类型检查提前到编译时执行,是代码更安全。
2 链表
处理一些类型相同的数据,习惯使用数组这种数据结构,但使用前必须定义数组大小,且不容易改变数组的大小,因为数组改变大小意味着放弃原有的全部单元。分配太多单元又会浪费宝贵的内存资源。动态增加或减少数据项时,可以使用链表这种数据结构。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
2.0 LinkedList < E >
泛型类
java.util
包中的LinkedList<E>
泛型类创建的对象以链表结构存储数据,习惯上称LinkedList
类创建的对象为链表对象。
LinkedList<String> list = new LinkedList<String>
创建了一个空双链表。
2.1 常用方法
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() 返回链表的长度,即节点的个数...
2.2 遍历链表
- 链表对象可以使用
iterator()
方法获取一个Iterator
对象,该对象就是针对当前链表的迭代器。 get(int index)
方法遍历
示例
MyLinkedList.java
//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类似,二者的本质区别就是:一个使用顺序结构,一个使用链表结构。
2.3 排序和查找
要对链表按某种大小关系排序,以便查找一个数据是否和链表某个节点上的数据相等。
如果链表实现了Comparable
接口的类的实例,如String对象(String实现了该接口)就可以使用Collections
类调用sort(List<E> list>)
方法可以对参数指定的列表排序,即按节点中存储的对象的大小升序排列节点。
Collections.sort(listString);// 按字典序排序
自定义的类可以实现泛型接口Comparable<E>
中的compareTo(E b)
方法来指定该类的示例相互比较大小关系的准则
a.compareTo(b)<0 称a小于ba.compareTo(b)>0 称a大于ba.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相等的数据
2.4 洗牌和旋转
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正值时,右转,负值,左转。
3 堆栈
堆栈是一种“后进先出”的数据结构,只能在一端进行输入和输出数据的操作。
使用java.util 包中的SStack<E>
泛型类创建一个堆栈对象
public E push(E item) 压栈public E pop() 出栈public boolean empty() 判断是否有数据,有false,无truepublic E peek() 获取栈顶端的数据,不能删除该数据public int search (Object data) 获取数据在堆栈中的位置,最顶段为1,向下依次增加,不含此数据返回-1
堆栈是很灵活的数据结构,使用堆栈可以节省内存的开销。例如,递归是很消耗内存的算法,我们可以借助堆栈消除大部分递归,达到和递归算法同样的目的。Fibonacci整数序列是我们熟悉的一个递归序列,它的第n项是前两项的和,第一项和第二项是1。
示例
用堆栈输出Fibonacci递归序列对的若干项。
//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++; } } }}
23581321345589144
4 散列映射
4.1 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)//添加数据
4.2 常用方法
public void clear() 清空散列映射 public Object clone() 返回当前散列映射的一个克隆 public int size() 返回散列映射的大小,即散列映射的键值对的个数 . .
4.3 遍历散列映射
public Collection<V> values()
方法返回一个实现Collection<V>
接口类创建的对象,可以使用接口回调技术,即将该对象的引用给Collection<V>
接口变量,该变量可以回调iterator()
方法获取一个Iterator
对象,这个Iterator
对象存放着散列映射中所有的”键值”对中的值。
word.txt
mountain 山 water 水 canvas 画 fish 鱼 dog 狗 vehicle 车辆 decay 腐败
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 腐败
4.4 基于散列映射的查询
示例
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山输入要查询的英文单词:
5 树集
5.1 TreeSet<E>
泛型类
TreeSet<E>
类是实现Set<E>
接口的类,它的大部分实现方法都是接口方法的实现。TreeSet<E>
类创建的对象称作树集。树集采用树结构存储数据,树节点的数据会按存放的数据的“大小”顺序一层一层地依次排列,同层中从左到右从小到大递增排列,下一层的都比上一层小
TreeSet<String> mytree = new TreeSet<String>();
mytree.add("boy");
5.2 节点的大小关系
树集节点的排列和链表不同,不按添加的先后顺序排列。树集用add方法添加节点,节点会按其存放的数据的”大小“ 顺序一层一层地依次排列。
自定义的类,这里使用了Comparable<E>
泛型接口中compareTo(E b)
方法来比较大小
5.3 TreeSet类常用方法
public boolean add(E o) 向树集添加节点,成功true public void clear() 删除树集中的所有节点 public E first() 返回树集中第一个节点的数据(最小的节点) public boolean remove(Object o) 删除树集中的存储参数指定的对象的最小节点,成功true . .
示例
MyTreeSet.java
//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
6 树映射
TreeMap<K,V>
类实现了Map<K,V>
接口,称TreeMap<K,V>
对象为树映射。
public V put(K key,V value) //添加节点
树映射的节点存储”关键字/值“对,树映射保证节点是按照节点中的关键字升序排列的。
示例
使用TreeMap,分别按照学生的身高和体重排序节点。
//package com.树映射;import java.util.*;class StudentKey implements Comparable<StudentKey> { double d = 0; public StudentKey(double d) { this.d = d; } @Override public int compareTo(StudentKey o) { if ((this.d - o.d) == 0) { return -1; } return (int) ((this.d - o.d) * 1000); }}class Student { String name = null; double weight, height; public Student(String name, double weight, double height) { super(); this.name = name; this.weight = weight; this.height = height; }}public class MyTreeMap { public static void main(String[] args) { final int NUMBER = 3; TreeMap<StudentKey, Student> treemap = new TreeMap<>(); String[] str = { "舒克", "贝塔", "坦克" }; double[] weight = { 78, 67, 45 }; double[] height = { 178, 156, 158 }; Student[] student = new Student[NUMBER]; for (int k = 0; k < student.length; k++) { student[k] = new Student(str[k], weight[k], height[k]);// 把数据存到student数组中 } StudentKey[] key = new StudentKey[NUMBER]; for (int k = 0; k < key.length; k++) { key[k] = new StudentKey(student[k].weight); // 把体重数据存到key数组中 } for (int k = 0; k < student.length; k++) { treemap.put(key[k], student[k]);// 存到树映射 按体重排序 } // System.out.println("treemap.keySet"+treemap.keySet()); // System.out.println("treemap.value()"+treemap.values()); // System.out.println("treemap"+treemap); System.out.println("按体重排序:"); Collection<Student> collection = treemap.values(); // 存储的只是value,然后排序 /** * Collection 集合接口, Collections * 是一个包装类,用于元素的排序,搜索及线程安全等操作,服务于Collection框架 */ Iterator<Student> iter = collection.iterator();// 迭代器,快速遍历集合 while (iter.hasNext()) { Student stu = iter.next(); System.out.println("姓名:" + stu.name + " 体重:" + stu.weight); } treemap.clear(); for (int k = 0; k < key.length; k++) { key[k] = new StudentKey(student[k].height); } for (int k = 0; k < student.length; k++) { treemap.put(key[k], student[k]);// 按身高排序 } System.out.println("按身高排序:"); collection = treemap.values(); iter = collection.iterator(); while (iter.hasNext()) { Student stu = iter.next(); System.out.println("姓名:" + stu.name + " 身高:" + stu.height); } treemap.clear(); }}
按体重排序:姓名:坦克 体重:45.0姓名:贝塔 体重:67.0姓名:舒克 体重:78.0按身高排序:姓名:贝塔 身高:156.0姓名:坦克 身高:158.0姓名:舒克 身高:178.0
7 自动装箱和拆箱
JDK1.5 新增了自动装箱和拆箱功能,在没有自动装箱和拆箱功能之前,不能将基本数据类型添加到类似链表的数据结构中。 JDK1.5后,程序允许这样的操作,系统会自动完成基本类型到相应对象的转换(自动装箱)。当从一个数据结构中获取的对象时,如果该对象是基本类型的封装对象,那么系统自动完成对象到基本类型的转换(自动拆箱)。
import java.util.*;public class Main { public static void main(String args[]) { ArrayList<Integer> list=new ArrayList<Integer>(); for(int i=0;i<10;i++) { list.add(i); //自动装箱,实际添加到list中的是new Integer(i)。 } for(int k=list.size()-1;k>=0;k--) { int m=list.get(k); //自动拆箱,获取Integer对象中的int型数据 System.out.printf("%3d",m); } }}
参考
《Java程序设计实用教程》
- Java笔记(8)-泛型、链表、LinkedList<E>、Iterator迭代器、Collections类方法、堆栈、HashMap<K,V>、TreeSet<E>、自动装箱和拆箱
- JAVA泛型? T K V E(收藏)
- Java泛型<T>,<E>,<k,v>含义
- JAVA泛型? T K V E含义
- 泛型?、K、V、T、E
- 泛型T E K V ?
- Java集合框架:ArrayList、LinkedList、HashSet、TreeSet、HashMap、Iterator
- JAVA泛型? T K V E等代表的意思
- java 泛型 E/T/K/V/N 代表的意义
- JAVA泛型? T K V E等代表的意思
- JAVA泛型? T K V E等代表的意思
- java 泛型 E/T/K/V/N 代表的意义
- JAVA泛型? T K V E等代表的意思
- JAVA泛型? T K V E等代表的意思
- JAVA泛型? T K V E等代表的意思
- java 泛型 E/T/K/V/N 代表的意义
- JAVA泛型? T K V E等代表的意思
- java中的T,E,K,V,?
- HD ACM C++ 1089
- 网易2017秋招编程题
- 十个最常用机器学习算法编码指南(Python版)
- Android Studio 多渠道打包和打包时设置包名
- HashMap和Hashtable及HashSet的区别
- Java笔记(8)-泛型、链表、LinkedList<E>、Iterator迭代器、Collections类方法、堆栈、HashMap<K,V>、TreeSet<E>、自动装箱和拆箱
- QT:QString和char*互转
- Unity 动画路径预览工具
- 第三届河南省程序设计大赛-NYOJ-247-虚拟的城市之旅(SPFA)
- out.writer输出
- ORACLE 12C新特性——CDB与PDB
- 代码设置弹出或关闭输入法
- KUKA profesafe
- lightoj 1003 拓扑裸题