java常用类库以及集合

泛型

概述

泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

使用

泛型类
定义一个泛型类:
    public class ClassName<T>{
        private T data;
        public T getData() {
            return data;
            }
        public void setData(T data) {
        	this.data = data;
        }
    }
泛型接口
public interface IntercaceName<T>{
T getData();
}

实现接口时,可以选择指定泛型类型,也可以选择不指定, 如下:
指定类型:
    public class Interface1 implements IntercaceName<String> {
    private String text;
    @Override
        public String getData() {	
        	return text;
        }
    }
不指定类型:
    public class Interface1<T> implements IntercaceName<T> {
        private T data;
        @Override
        public T getData() {
        	return data;
        }
    }
泛型方法
private static <T> T 方法名(T a, T b) {}
泛型限制类型
1. 在使用泛型时, 可以指定泛型的限定区域 ,
    - 例如: 必须是某某类的子类或 某某接口的实现类,格式:
   		 <T extends 类或接口1 & 接口2>
泛型中的通配符 “ ? ”
类型通配符是使用?代替方法具体的类型实参。
    1 <? extends Parent> 指定了泛型类型的上届
    2 <? super Child> 指定了泛型类型的下届
    3 <?> 指定了没有限制的泛型类型

?可以当作object来使用,但是用起来有区别。

作用

  1. 提高代码复用率
  2. 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)

注意

  1. 在编译之后程序会采取去泛型化的措施。
  2. 也就是说Java中的泛型,只在编译阶段有效。
  3. 在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加
  4. 类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

Object是所有类的父类

Arrays

  • 该类包含用于操作数组的各种方法(例如排序和搜索)。
  • 如果指定的数组引用为null,则此类中的方法都抛出NullPointerException

arrays的常用的方法

  1. toString(Object [] a) 返回指定数组内容的字符串 表现形试
  2. sort(Object[] a) 将指定的数组按升序排序
  3. sort(Object[] a, int formIndex, int toIndex) 按升序对指定数组进行排序
  4. mismatch(Object[] a , Object[] b) 查找并返回两个Object数组之间第一个不匹配的索引,找不到的话返回 -1 .
  5. copyOfRange(T[] orginal, int from , int to) 将指定范围的数组复制到新数组中
  6. copyOf(T[] array ,int length) 将数组array扩容到length长度

Math

  • 类Math包含用于执行基本数字运算的方法, 例如基本指数,对数,平方根和三角函数
常用方法
  1. abs(double a) 返回double值的绝对值
  2. max(int a, int b) 返回int值中较大的那个
  3. min (int a, int b) 返回int值中较大的那个

Date

  • Date类表示特定的时刻,精度为毫秒
  • Date类还有两个附加功能。它允许将日期解释为年,月,日,小时,分钟和秒值。它还允许格式化和解析日期字符串

获取当前时间 Date date = new Date();
getTime 获取当前的毫秒数

DateFormat

  • DateFormat是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化和分析日期或时间
  • DateFormat可帮助您格式化和解析任何区域设置的日期。

image-20220305155406468

/**
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 对象创建

image-20220305155432167

注意:

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的其他方法

image.png

StringBuffer 和 StringBuilder 类

  • 当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
  • 和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象
注意:

StringBuilder 和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

StringBuffer方法

image.png

集合

1、类集设置的目的

				普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最 早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构, 所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现 

 类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口 
  • Collection: 主要存放单个数据(单指集合)
  • Map : 主要存放两个数据—键值对 key–value 的形式(双指集合)
  • Interator:迭代器,获取数据结构数据的最 优方式(输出)

类集是java最数据结构成熟的体现,里面封装所有数据结构类型,直接调用接口即可使用
image.png

集合的概述

集合:集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组既然都是容器,它们有啥区别呢?

  1. 数组的长度是固定的。集合的长度是可变的
  2. 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类 型可以不一致。在开发中一般当对象多的时候,使用集合进行存储

2、Collection接口

Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。

接口定义
publice interface Collection<E> extends Iterable<E>

15种常用的方法
image.png

  1. 在开发中不会直接使用 Collection 接口。而使用其操作的子接口:List、Set。

3、List接口

		java.util.List 接口继承自 Collection 接口 ,将实现了 List 接口的对象称为List集合 
  1.  在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,
    
  2.  在程序中可以通过索引来访问集合中的指定元素 
    
  3.  List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
    
  4.  通过元素的equals方法,来比较是否为重复的元素    
    
list接口定义
public interface List<E> extends Collection<E>

List接口中常用方法

  • 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<String> all = new ArrayList<String>(); // 实例化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<String> all = new ArrayList<String>(); // 实例化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接口单独定义的
            }
    }
}

常用的方法
image.png

5、Vector

与 ArrayList 一样,Vector 本身也属于 List 接口的子类,

public class Vector<E> extends AbstractList<E>
implements List<E>, 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<String> all = new Vector<String>(); // 实例化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稍微没那么安全
image.png

7、LinkedList

java.util.LinkedList 集合数据存储的结构是链表结构。方便元素添加、删除的集合

ArrayList 和 LinkedList 的区别

Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低
以下情况使用 ArrayList :

  • 频繁访问列表中的某一个元素。
  • 只需要在列表末尾进行添加和删除元素操作。

以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
public class RunoobTest {  //我们可以使用 for 配合 size() 方法来迭代列表中的元素
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        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<String> sites = new LinkedList<String>();
        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<String> all = new HashSet<String>(); // 实例化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<String> all = new HashSet<String>(); // 实例化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<String> all = new HashSet<String>(); // 实例化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 的区别(重点)

image.png

TreeSet 排序 的子类

  1. TreeSet不允许null值;
  2. TreeSet不是线程安全的
  3. 和SortedMap一样,支持自然排序自定义排序。自然排序要求添加到Set中的元素实现Comparable接口,自定义排序要求实现一个Comparator比较器

与 HashSet 不同的是,TreeSet 本身属于排序的子类,此类的定义如下:

public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable

示例:

package org.listdemo.treesetdemo01;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo01 {
    public static void main(String[] args) {
    Set<String> all = new TreeSet<String>(); // 实例化Set接口对象\
    all.add("D");
    all.add("X");
    all.add("A");
    System.out.println(all);
    }
}

输出:[A, D, X]

虽然在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。

排序的说明

定义一个类进行对象排序

示例

定义person类
public class Person implements Comparable<Person> {
    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<Person> all = new TreeSet<Person>();
        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 进行输出。”

Iterator

Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出.

publice interface Iterator<E>

要想使用此接口,则必须使用 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<String> all = new ArrayList<String>();
        all.add("A");
        all.add("B");
        all.add("C");
        all.add("D");
        all.add("E");
        Iterator<String> iter = all.iterator();
        while (iter.hasNext()) {// 判断是否有下一个元素
        	String str = iter.next(); // 取出当前元素
       		System.out.print(str + "、");
        }
    }
}
	以上的操作是 Iterator 接口使用最多的形式,也是一个标准的输出形式。


	但是在使用 Iterator 输出的时候有一点必须注意,在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator 接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。
Iterator<String> iter = all.iterator();
while (iter.hasNext()) {// 判断是否有下一个元素
    String str = iter.next(); // 取出当前元素
    if (str.equals("C")) {
   	 	iter.remove(); // 调用Iterator中的删除
    } else {
    	System.out.print(str + "、");
    }
}

ListIterator

  • ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口
  • ListIterator 是可以进行双向输出的迭代接口,

ListIterator 和 lterator

相同:都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用

不同:

  1. 使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型(即不能对Map进行使用)
  2. ListIterator有add方法,可以向List中添加对象,而Iterator不能。
  3. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历
  4. 都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现

foreach

foreach 可以用来输出数组的内容,那么也可以输出集合中的内容。

import java.util.ArrayList;
import java.util.Collection;
public class ForeachDemo01 {
    public static void main(String[] args) {
        Collection<String> all = new ArrayList<String>();
        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
image.png

新的子类:HashMap

  • 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<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "张三A");
        map.put(2, "李四");
        map.put(3, "王五");
        Set<Integer> set = map.keySet(); // 得到全部的key
        Collection<String> value = map.values(); // 得到全部的value
        Iterator<Integer> iter1 = set.iterator();
        Iterator<String> 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<String, String> map = new HashMap<String, String>();
    map.put("ZS", "张三");
    map.put("LS", "李四");
    map.put("WW", "王五");
    map.put("ZL", "赵六");
    map.put("SQ", "孙七");
    Set<String> set = map.keySet(); // 得到全部的key
    Iterator<String> iter = set.iterator();
    while (iter.hasNext()) {
        String i = iter.next(); // 得到key
        System.out.println(i + " --:> " + map.get(i));
    }
}

Hashtable

image.png

TreeMap 子类是允许 key 进行排序的操作子类,其本身在操作的时候将按照 key 进行排序,另外,key 中的内容可以 为任意的对象,但是要求对象所在的类必须实现 Comparable 接口。

public static void main(String[] args) {
    Map<String, String> map = new TreeMap<String, String>();
    map.put("ZS", "张三");
    map.put("LS", "李四");
    map.put("WW", "王五");
    map.put("ZL", "赵六");
    map.put("SQ", "孙七");
    Set<String> set = map.keySet(); // 得到全部的key
    Iterator<String> 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是在具体的应用过程中我们根据需求创建一个工具类来完成比较,相比之下比较器的使用更加灵活,不会改变这个类本身,减低了耦合度。

总结

  1. 类集就是一个动态的对象数组,可以向集合中加入任意多的内容。
  2. List 接口中是允许有重复元素的,Set 接口中是不允许有重复元素。
  3. 所有的重复元素依靠 hashCode()和 equals 进行区分
  4. List 接口的常用子类:ArrayList、Vector
  5. Set 接口的常用子类:HashSet、TreeSet
  6. TreeSet 是可以排序,一个类的对象依靠 Comparable 接口排序
  7. Map 接口中允许存放一对内容,key value
  8. Map 接口的子类:HashMap、Hashtable、TreeMap
  9. Map 使用 Iterator 输出的详细步骤

补充小知识

链表和数组的区别

什么 是链表?

链表 [Linked List]:链表是由一组不必相连(不必相连:可以连续也可以不连续)的内 存结构(节点),按特定的顺序链接在一起的抽象数据类型。

补充:

  • 抽象数据类型(Abstract Data Type [ADT]):表示数学中抽象出来的一些操作的集合。
  • 内存结构:内存中的结构,如:struct、特殊内存块…等等之类;
数组和链表的区别和优缺点:
**数组**:
    数组是一种连续存储线性结构,元素类型相同,大小相等   

数组的优点 :
存储速度快
数组的缺点:

  1. 事先必须知道数组的长度
  2. 插入删除元素很慢
  3. 空间通常是有限制的
  4. 需要大块连续的内存块
  5. 插入删除元素的效率很低

链表
链表是离散存储线性结构
n 个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一 个后续节点,首节点没有前驱节点,尾节点没有后续节点。

链表优点:
空间没有限制
插入删除元素很快
链表缺点:
存取速度很慢

**链表共分为3类: 单链表、双向链表、循环链表 **
image.png

二叉树

二叉树是树的一种,每个节点最多可具有两个子树,即结点的度最大为 2(结点度:结点拥 有的子树数)。
image.png

二叉查找树

定义:当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。 o 可以看出,这对我们来找一个数是非常方便快捷的
image.png

二叉树的种类
斜树

所有结点都只有左子树,或者右子树。
image.png

满二叉树

所有的分支节点都具有左右节点。
image.png

完全二叉树

若设二叉树的深度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
image.png

二叉树的一些性质
  1. 二叉树第 i 层上的结点数目最多为 2^(i-1) (i≥1)
  2. 深度为 h 的二叉树至多有 2^h-1 个结点(h≥1)
  3. 包含 n 个结点的二叉树的高度至少为 log2 (n+1)
  4. 在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0=n2+1
二叉树的遍历方式
 **二叉树的遍历方式,一般分为先序遍历,中序遍历,后序遍历。 **

先序遍历

先访问根节点,然后访问左节点,最后访问右节点(根->左->右) •
中序遍历 o
先访问左节点,然后访问根节点,最后访问右节点(左->根->右) •
后序遍历 o
先访问左节点,然后访问右节点,最后访问根节点(左->右->根
image.png

常见的数据结构

数据存储的常用结构有:栈、队列、数组、链表和红黑树

栈:stack,又称堆栈, 栈(stack)是限定仅在表尾进行插入和删除操作的线性表。我们把允许插 入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为先进后出 的线性表 。

特点:

  • 先进后出
  • 栈的入口、出口的都是栈的顶端位置

image.png

队列

队列:queue,简称队, 队列是一种特殊的线性表,是运算受到限制的一种线性表,只允许在表的 一端进行插入,而在另一端进行删除元素的线性表。队尾(rear)是允许插入的一端。队头(front)是 允许删除的一端。空队列是不含元素的空表。

特点:

  • 先进先出
  • 队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口

image.png

数组:
  • 数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。

特点:

  • 查找元素快:通过索引,可以快速访问指定位置的元素
  • 增删元素慢
  1. 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原 数组元素根据索引,复制到新数组对应索引的位置。
  2. 指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应 索引的位置,原数组中指定索引位置元素不复制到新数组中。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值