泛型
概述使用
泛型类泛型接口泛型方法泛型限制类型泛型中的通配符 “ ? ” 作用注意 Arrays
arrays的常用的方法 Math
常用方法 Date
DateFormat String
注意:字符串长度连接字符串String的其他方法 StringBuffer 和 StringBuilder 类
注意: StringBuffer方法 集合
1、类集设置的目的
集合的概述 2、Collection接口3、List接口
List接口中常用方法 4、ArrayList接口5、Vector6、Vector类和ArrayList类的区别7、linkedList
ArrayList 和 linkedList 的区别 Set接口
散列存放:HashSetHashMap 与 Hashtable 的区别(重点)image.pngTreeSet 排序 的子类排序的说明 集合输出
IteratorListIteratorListIterator 和 lteratorforeach Map接口
新的子类:HashMapHashtableimage.png关于 Map 集合的输出Comparable和Comparator两个接口的区别 总结 补充小知识
链表和数组的区别
什么 是链表?数组和链表的区别和优缺点: 二叉树
二叉查找树二叉树的种类
斜树满二叉树完全二叉树 二叉树的一些性质二叉树的遍历方式 常见的数据结构
栈队列数组:
泛型 概述泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
使用 泛型类定义一个泛型类:
public class ClassName{
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型接口
public interface IntercaceName泛型方法{ T getData(); } 实现接口时,可以选择指定泛型类型,也可以选择不指定, 如下: 指定类型: public class Interface1 implements IntercaceName { private String text; @Override public String getData() { return text; } } 不指定类型: public class Interface1 implements IntercaceName { private T data; @Override public T getData() { return data; } }
private static泛型限制类型T 方法名(T a, T b) {}
1. 在使用泛型时, 可以指定泛型的限定区域 ,
- 例如: 必须是某某类的子类或 某某接口的实现类,格式:
泛型中的通配符 “ ? ”
类型通配符是使用?代替方法具体的类型实参。
1 extends Parent> 指定了泛型类型的上届
2 super Child> 指定了泛型类型的下届
3 > 指定了没有限制的泛型类型
?可以当作object来使用,但是用起来有区别。
作用- 提高代码复用率泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
- 在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
Object是所有类的父类
该类包含用于操作数组的各种方法(例如排序和搜索)。如果指定的数组引用为null,则此类中的方法都抛出NullPointerException arrays的常用的方法
- toString(Object [] a) 返回指定数组内容的字符串 表现形试sort(Object[] a) 将指定的数组按升序排序sort(Object[] a, int formIndex, int toIndex) 按升序对指定数组进行排序mismatch(Object[] a , Object[] b) 查找并返回两个Object数组之间第一个不匹配的索引,找不到的话返回 -1 .copyOfRange(T[] orginal, int from , int to) 将指定范围的数组复制到新数组中copyOf(T[] array ,int length) 将数组array扩容到length长度
类Math包含用于执行基本数字运算的方法, 例如基本指数,对数,平方根和三角函数 常用方法
- abs(double a) 返回double值的绝对值max(int a, int b) 返回int值中较大的那个min (int a, int b) 返回int值中较大的那个
Date类表示特定的时刻,精度为毫秒Date类还有两个附加功能。它允许将日期解释为年,月,日,小时,分钟和秒值。它还允许格式化和解析日期字符串
获取当前时间 Date date = new Date();
getTime 获取当前的毫秒数
DateFormat是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化和分析日期或时间DateFormat可帮助您格式化和解析任何区域设置的日期。
/**
y : 年
M : 月
d : 日
H : 时
m : 分
s : 秒
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss")
String text = format.format(new Date())
// 以年月日的形式输出当前时间
String
String类表示字符串在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。String 是被 final 修饰的,他的长度是不可变的,就算调用 String 的 concat 方法,那也是把字符串拼接起来并重新创建一个对象
创建字符串有两种方法
直接赋值
String str = "Ruboob";
用构造函数创建字符串
String str2 = new String("Ruboob");
String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上:
String s1 = "Runoob"; // String 直接创建
String s2 = "Runoob"; // String 直接创建
String s3 = s1; // 相同引用
String s4 = new String("Runoob"); // String 对象创建
String s5 = new String("Runoob"); // String 对象创建
注意:
String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了
如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。
String 类的一个访问器方法是 length() 方法,它返回字符串对象包含的字符数
public class StringDemo {
public static void main(String args[]) {
String site = "www.runoob.com";
int len = site.length();
System.out.println( "菜鸟教程网址长度 : " + len );
}
} // 输出 菜鸟教程网址长度 : 14
连接字符串
String 类提供了连接两个字符串的方法:
//返回 string2 连接 string1 的新字符串。也可以对字符串常量使用 concat() 方法 string1.concat(string2); //更常用的是使用'+'操作符来连接字符串,如: "Hello," + " runoob" + "!"String的其他方法 StringBuffer 和 StringBuilder 类
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象 注意:
StringBuilder 和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最 早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构, 所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现 类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口
Collection: 主要存放单个数据(单指集合)Map : 主要存放两个数据—键值对 key–value 的形式(双指集合)Interator:迭代器,获取数据结构数据的最 优方式(输出)
类集是java最数据结构成熟的体现,里面封装所有数据结构类型,直接调用接口即可使用
集合:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有啥区别呢?
- 数组的长度是固定的。集合的长度是可变的数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类 型可以不一致。在开发中一般当对象多的时候,使用集合进行存储
Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。
接口定义 publice interface Collectionextends Iterable
15种常用的方法
- 在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。
java.util.List 接口继承自 Collection 接口 ,将实现了 List 接口的对象称为List集合
在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,
在程序中可以通过索引来访问集合中的指定元素
List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
通过元素的equals方法,来比较是否为重复的元素
list接口定义 public interface ListList接口中常用方法extends Collection
public void add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。public E get(int index) :返回集合中指定位置的元素。public E remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新 前的元素。
List 接口之后,那么该如何使用该接口呢?需要找到此接口的实现类,常用的实现类有如下几个: · ArrayList(95%)、Vector(4%)、linkedList(1%)
4、ArrayList接口java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用 最多的功能为查询数据、遍历数据 ,ArrayList 继承了 AbstractList ,并实现了 List 接口
此类继承了 AbstractList 类。AbstractList 是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。
范例:增加及取得元素
package org.listdemo.arraylistdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo01 {
public static void main(String[] args) {
List all = new ArrayList(); // 实例化List对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从Collection接口继承而来
all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
all.add("world"); // 增加内容,此方法从Collection接口继承而来
System.out.println(all); // 打印all对象调用toString()方法
}
}
以上的操作向集合中增加了三个元素,其中在指定位置增加的操作是 List 接口单独定义的。随后进行输出的时候, 实际上调用的是 toString()方法完成输出的。
范例:进一步操作
使用 remove()方法删除若干个元素,并且使用循环的方式输出。根据指定位置取的内容的方法,只有 List 接口才有定义,其他的任何接口都没有任何的定义
package org.listdemo.arraylistdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo02 {
public static void main(String[] args) {
List all = new ArrayList(); // 实例化List对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从Collection接口继承而来
all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
all.add("world"); // 增加内容,此方法从Collection接口继承而来
all.remove(1); // 根据索引删除内容,此方法是List接口单独定义的
all.remove("world");// 删除指定的对象
System.out.print("集合中的内容是:");
for (int x = 0; x < all.size(); x++) { // size()方法从Collection接口继承而来
System.out.print(all.get(x) + "、"); // 此方法是List接口单独定义的
}
}
}
常用的方法
与 ArrayList 一样,Vector 本身也属于 List 接口的子类,
public class Vectorextends AbstractList implements List , RandomAccess, Cloneable, Serializable
此类与 ArrayList 类一样,都是 AbstractList 的子类。所以,此时的操作只要是 List 接口的子类就都按照 List 进行操作。
package org.listdemo.vectordemo;
import java.util.List;
import java.util.Vector;
public class VectorDemo01 {
public static void main(String[] args) {
List all = new Vector(); // 实例化List对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从Collection接口继承而来
all.add(0, "LAMP ");// 增加内容,此方法是List接口单独定义的
all.add("world"); // 增加内容,此方法从Collection接口继承而来
all.remove(1); // 根据索引删除内容,此方法是List接口单独定义的
all.remove("world");// 删除指定的对象
System.out.print("集合中的内容是:");
for (int x = 0; x < all.size(); x++) { // size()方法从Collection接口继承而来
System.out.print(all.get(x) + "、"); // 此方法是List接口单独定义的
}
}
}
以上的操作结果与使用 ArrayList 本身并没有任何的区别。因为操作的时候是以接口为操作的标准。
但是 Vector 属于 Java 元老级的操作类,是最早的提供了动态对象数组的操作类,在 JDK 1.0 的时候就已经推出了此 类的使用,只是后来在 JDK 1.2 之后引入了 Java 类集合框架。但是为了照顾很多已经习惯于使用 Vector 的用户,所以在 JDK 1.2 之后将 Vector 类进行了升级了,让其多实现了一个 List 接口,这样才将这个类继续保留了下来6、Vector类和ArrayList类的区别
vector线程安全,arraylist稍微没那么安全
java.util.linkedList 集合数据存储的结构是链表结构。方便元素添加、删除的集合
ArrayList 和 linkedList 的区别Java linkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
与 ArrayList 相比,linkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低
以下情况使用 ArrayList :
频繁访问列表中的某一个元素。只需要在列表末尾进行添加和删除元素操作。
以下情况使用 linkedList :
你需要通过循环迭代来访问列表中的某些元素。需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
public class RunoobTest { //我们可以使用 for 配合 size() 方法来迭代列表中的元素
public static void main(String[] args) {
linkedList sites = new linkedList();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
for (String i : sites) {
System.out.println(i);
}
}
}
输出结果为:
Google
Runoob
Taobao
Weibo
public class RunoobTest {
public static void main(String[] args) {
linkedList sites = new linkedList();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
// 使用 addFirst() 在头部添加元素
sites.addFirst("Wiki");
System.out.println(sites);
}
}
//[Wiki, Google, Runoob, Taobao]
Set接口
Set 接口也是 Collection 的子接口,与 List 接口最大的不同在于,Set 接口里面的内容是不允许重复的。Set 接口并没有对 Collection 接口进行扩充,基本上还是与 Collection 接口保持一致。因为此接口没有 List 接口中定义 的 get(int index)方法,所以无法使用循环进行输出。那么在此接口中有两个常用的子类:HashSet、TreeSet 散列存放:HashSet
HashSet 属于散列的存放类集,里面的内容是无序存放的。
注意: 给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方 式,才能保证HashSet集合中的对象唯一
范例:
package org.listdemo.hashsetdemo;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo01 {
public static void main(String[] args) {
Set all = new HashSet(); // 实例化Set接口对象
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
System.out.println(all);
}
}
HashSet本身属于无序存放,要实现通过循环的方式输出Set中的内容,可以先转变为数组
将hashSet变为数组 toArray();
package org.listdemo.hashsetdemo;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo02 {
public static void main(String[] args) {
Set all = new HashSet(); // 实例化Set接口对象
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
Object obj[] = all.toArray(); // 将集合变为对象数组
for (int x = 0; x < obj.length; x++) {
System.out.print(obj[x] + "、");
}
}
}
但是,以上的操作不好,因为在操作的时候已经指定了操作的泛型类型,那么现在最好的做法是由泛型所指定的类 型变为指定的数组。 所以只能使用以下的方法: T[] to Array(T[] a)
String[] str = all.toArray(new String[] {});
package org.listdemo.hashsetdemo;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo03 {
public static void main(String[] args) {
Set all = new HashSet(); // 实例化Set接口对象
all.add("A");Java SE 核心技术
第(8)页 共(27)页
all.add("B");
all.add("C");
all.add("D");
all.add("E");
String[] str = all.toArray(new String[] {});// 变为指定的泛型类型数组
for (int x = 0; x < str.length; x++) {
System.out.print(str[x] + "、");
}
}
}
HashMap 与 Hashtable 的区别(重点)
TreeSet 排序 的子类
- TreeSet不允许null值;TreeSet不是线程安全的和SortedMap一样,支持自然排序和自定义排序。自然排序要求添加到Set中的元素实现Comparable接口,自定义排序要求实现一个Comparator比较器
与 HashSet 不同的是,TreeSet 本身属于排序的子类,此类的定义如下:
public class TreeSetextends AbstractSet implements NavigableSet , Cloneable, Serializable
示例:
package org.listdemo.treesetdemo01;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo01 {
public static void main(String[] args) {
Set all = new TreeSet(); // 实例化Set接口对象
all.add("D");
all.add("X");
all.add("A");
System.out.println(all);
}
}
输出:[A, D, X]
虽然在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。
排序的说明定义一个类进行对象排序
示例
定义person类 public class Person implements Comparable{ private String name; private int age; public int compareTo(Person per) { if (this.age > per.age) { return 1; } else if (this.age < per.age) { return -1; } else { return 0; } } public Person() { } public Person(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; } public String toString() { return "姓名:" + this.name + ",年龄:" + this.age; } }
定义一个TreeSet集合,向里面增加若干个 Person 对象。
import java.util.Set;
import java.util.TreeSet;
public class TreeSetPersonDemo01 {
public static void main(String[] args) {
Set all = new TreeSet();
all.add(new Person("张三", 10));
all.add(new Person("李四", 10));
all.add(new Person("王五", 11));
all.add(new Person("赵六", 12));
all.add(new Person("孙七", 13));
System.out.println(all);
}
}
结果是:[姓名:张三,年龄:10, 姓名:王五,年龄:11, 姓名:赵六,年龄:12, 姓名:孙七,年龄:13]
从以上的结果中可以发现,李四没有了。因为李四的年龄和张三的年龄是一样的,所以会被认为是同一个对象。则 此时必须修改 Person 类,如果假设年龄相等的话,按字符串进行排序。
public int compareTo(Person per) {
if (this.age > per.age) {
return 1;
} else if (this.age < per.age) {
return -1;
} else {
return this.name.compareTo(per.name);
}
}
小结:
关于 TreeSet 的排序实现,如果是集合中对象是自定义的或者说其他系统定义的类没有实现 Comparable 接口,则不能实现 TreeSet 的排序,会报类型转换(转向 Comparable 接口)错误。 换句话说要添加到 TreeSet 集合中的对象的类型必须实现了 Comparable 接口。
不过 TreeSet 的集合因为借用了 Comparable 接口,同时可以去除重复值,而 HashSet 虽然是 Set 接口子类,但是对于没有复写 Object 的 equals 和 hashCode 方法的对象,加入了 HashSet 集合中也是不能去掉重复值的集合输出
已经学习过了基本的集合操作,那么对于集合的输出本身也是有多种形式的,可以使用如下的几种方式:
Iterator 迭代输出(90%)、ListIterator(5%)、Enumeration(1%)、foreach(4%)
但是在讲解输出的时候一定要记住以下的原则:“只要是碰到了集合,则输出的时候想都不想就使用 Iterator 进行输出。”
IteratorIterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出.
publice interface Iterator
要想使用此接口,则必须使用 Collection 接口,在 Collection 接口中规定了一个 iterator()方法,可以用于为 Iterator 接口进行实例化操作。
迭代 : 即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果 有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取 出。这种取出方式专业术语称为迭代。public E next() :返回迭代的下一个元素。public boolean hasNext() :如果仍有元素可以迭代,则返回 true
此接口规定了以下的三个方法:
范例:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo01 {
public static void main(String[] args) {
Collection all = new ArrayList();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
Iterator iter = all.iterator();
while (iter.hasNext()) {// 判断是否有下一个元素
String str = iter.next(); // 取出当前元素
System.out.print(str + "、");
}
}
}
以上的操作是 Iterator 接口使用最多的形式,也是一个标准的输出形式。 但是在使用 Iterator 输出的时候有一点必须注意,在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator 接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。
IteratorListIteratoriter = all.iterator(); while (iter.hasNext()) {// 判断是否有下一个元素 String str = iter.next(); // 取出当前元素 if (str.equals("C")) { iter.remove(); // 调用Iterator中的删除 } else { System.out.print(str + "、"); } }
ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口ListIterator 是可以进行双向输出的迭代接口, ListIterator 和 lterator
相同:都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用
不同:
- 使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型(即不能对Map进行使用)ListIterator有add方法,可以向List中添加对象,而Iterator不能。ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现
foreach 可以用来输出数组的内容,那么也可以输出集合中的内容。
import java.util.ArrayList;
import java.util.Collection;
public class ForeachDemo01 {
public static void main(String[] args) {
Collection all = new ArrayList();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
for (String str : all) {
System.out.println(str) ;
}
}
}
for(类型 定义名 :要输出的对象){
System.out.println(定义名) ;
}
在使用 foreach 输出的时候一定要注意的是,里面的操作泛型要指定具体的类型,这样在输出的时候才会更加有针对 性。
Map接口以上的 Collection 中,每次操作的都是一个对象,如果现在假设要操作一对对象,则就必须使用 Map 了,类似于以 下一种情况:
· 张三 123456· 李四 23456
那么保存以上信息的时候使用 Collection 就不那么方便,所以要使用 Map 接口。里面的所有内容都按照 key ->value 的形式保存,也称为二元偶对象。
Map 本身是一个接口,所以一般会使用以下的几个子类:HashMap、TreeMap、Hashtable
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。HashMap 是无序的,即不会记录插入的顺序。HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口
范例:得到全部的 key 或 value
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapDemo02 {
public static void main(String[] args) {
Map map = new HashMap();
map.put(1, "张三A");
map.put(2, "李四");
map.put(3, "王五");
Set set = map.keySet(); // 得到全部的key
Collection value = map.values(); // 得到全部的value
Iterator iter1 = set.iterator();
Iterator iter2 = value.iterator();
System.out.print("全部的key:");
while (iter1.hasNext()) {
System.out.print(iter1.next() + "、");
}
System.out.print("n全部的value:");
while (iter2.hasNext()) {
System.out.print(iter2.next() + "、");
}
}
}
既然可以取得全部的 key,那么下面就可以对以上的操作进行扩充,循环输出 Map 中的全部内容。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapDemo03 {
public static void main(String[] args) {
Map map = new HashMap();
map.put("ZS", "张三");
map.put("LS", "李四");
map.put("WW", "王五");
map.put("ZL", "赵六");
map.put("SQ", "孙七");
Set set = map.keySet(); // 得到全部的key
Iterator iter = set.iterator();
while (iter.hasNext()) {
String i = iter.next(); // 得到key
System.out.println(i + " --:> " + map.get(i));
}
}
Hashtable
TreeMap 子类是允许 key 进行排序的操作子类,其本身在操作的时候将按照 key 进行排序,另外,key 中的内容可以 为任意的对象,但是要求对象所在的类必须实现 Comparable 接口。
public static void main(String[] args) {
Map map = new TreeMap();
map.put("ZS", "张三");
map.put("LS", "李四");
map.put("WW", "王五");
map.put("ZL", "赵六");
map.put("SQ", "孙七");
Set set = map.keySet(); // 得到全部的key
Iterator iter = set.iterator();
while (iter.hasNext()) {
String i = iter.next(); // 得到key
System.out.println(i + " --:> " + map.get(i));
}
}
关于 Map 集合的输出
在 Collection 接口中,可以使用 iterator()方法为 Iterator 接口实例化,并进行输出操作,但是在 Map 接口中并没有此 方法的定义,所以 Map 接口本身是不能直接使用 Iterator 进行输出的。
Comparable和Comparator两个接口的区别自然排序Comparable与比较器排序Comparator
Comparable:
强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码 实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进 行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构 (如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序
总结:自然排序Comparable是类在创建的时候就规定了类的比较的特性,而比较器Comparator是在具体的应用过程中我们根据需求创建一个工具类来完成比较,相比之下比较器的使用更加灵活,不会改变这个类本身,减低了耦合度。
总结- 类集就是一个动态的对象数组,可以向集合中加入任意多的内容。List 接口中是允许有重复元素的,Set 接口中是不允许有重复元素。所有的重复元素依靠 hashCode()和 equals 进行区分List 接口的常用子类:ArrayList、VectorSet 接口的常用子类:HashSet、TreeSetTreeSet 是可以排序,一个类的对象依靠 Comparable 接口排序Map 接口中允许存放一对内容,key valueMap 接口的子类:HashMap、Hashtable、TreeMapMap 使用 Iterator 输出的详细步骤
链表 [linked List]:链表是由一组不必相连(不必相连:可以连续也可以不连续)的内 存结构(节点),按特定的顺序链接在一起的抽象数据类型。
补充:
抽象数据类型(Abstract Data Type [ADT]):表示数学中抽象出来的一些操作的集合。内存结构:内存中的结构,如:struct、特殊内存块…等等之类; 数组和链表的区别和优缺点:
**数组**:
数组是一种连续存储线性结构,元素类型相同,大小相等
数组的优点 :
存储速度快
数组的缺点:
- 事先必须知道数组的长度插入删除元素很慢空间通常是有限制的需要大块连续的内存块插入删除元素的效率很低
链表:
链表是离散存储线性结构
n 个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一 个后续节点,首节点没有前驱节点,尾节点没有后续节点。
链表优点:
空间没有限制
插入删除元素很快
链表缺点:
存取速度很慢
**链表共分为3类: 单链表、双向链表、循环链表 **
二叉树是树的一种,每个节点最多可具有两个子树,即结点的度最大为 2(结点度:结点拥 有的子树数)。
定义:当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。 o 可以看出,这对我们来找一个数是非常方便快捷的
所有结点都只有左子树,或者右子树。
所有的分支节点都具有左右节点。
若设二叉树的深度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
- 二叉树第 i 层上的结点数目最多为 2^(i-1) (i≥1)深度为 h 的二叉树至多有 2^h-1 个结点(h≥1)包含 n 个结点的二叉树的高度至少为 log2 (n+1)在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0=n2+1
**二叉树的遍历方式,一般分为先序遍历,中序遍历,后序遍历。 **
先序遍历
先访问根节点,然后访问左节点,最后访问右节点(根->左->右) •
中序遍历 o
先访问左节点,然后访问根节点,最后访问右节点(左->根->右) •
后序遍历 o
先访问左节点,然后访问右节点,最后访问根节点(左->右->根
数据存储的常用结构有:栈、队列、数组、链表和红黑树
栈栈:stack,又称堆栈, 栈(stack)是限定仅在表尾进行插入和删除操作的线性表。我们把允许插 入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为先进后出 的线性表 。
特点:
先进后出栈的入口、出口的都是栈的顶端位置
队列队列:queue,简称队, 队列是一种特殊的线性表,是运算受到限制的一种线性表,只允许在表的 一端进行插入,而在另一端进行删除元素的线性表。队尾(rear)是允许插入的一端。队头(front)是 允许删除的一端。空队列是不含元素的空表。
特点:
先进先出队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口
数组:数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。
特点:
查找元素快:通过索引,可以快速访问指定位置的元素增删元素慢
- 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原 数组元素根据索引,复制到新数组对应索引的位置。指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应 索引的位置,原数组中指定索引位置元素不复制到新数组中。



