学习路线

本文是Java高级编程精华笔记,是对菜鸟教程中Java面向对象和Java高级编程的重要章节进行了学习,整理形成的学习笔记,知识图谱如下图所示:

Java高级应用与开发答案 java高级编程_java

继承

Java使用extends关键字来声明继承:

class 父类 {
}

class 子类 extends 父类 {
}

示例,子类企鹅和子类老鼠继承父类动物:

//父类:动物
public class Animal {
    private String name;
    private int id;

    public Animal(String myName, int myid) {
        name = myName;
        id = myid;
    }

    public void eat() {
        System.out.println(name + "正在吃");
    }

    public void sleep() {
        System.out.println(name + "正在睡");
    }

    public void introduction() {
        System.out.println("大家好!我是" + id + "号" + name + ".");
    }
}
//子类:企鹅
public class Penguin extends Animal { 
    public Penguin(String myName, int myid) { 
        super(myName, myid); 
    } 
}
//子类:老鼠
public class Mouse extends Animal { 
    public Mouse(String myName, int myid) { 
        super(myName, myid); 
    } 
}

Java只支持单继承,不支持多继承,但可以多重继承:

Java高级应用与开发答案 java高级编程_hashmap_02

  • 子类会继承父类的非private属性、方法。
  • 子类可以扩展自己的属性、方法。
  • 子类可以覆盖父类的方法,用自己的方式实现。

也就是,你的是我的,我的还是我的,我还可以改变你的

  • 构造器,子类不会继承父类,而且如果父类的构造器有参数,子类必须通过super关键字显式调用。

也就是,你老子始终是你老子

implements关键字

前面说到了Java使用extends声明继承类,而implements用来声明实现接口,并且可以同时实现多个接口。

public interface A {
    public void eat();
    public void sleep();
}

public interface B {
    public void show();
}

public class C implements A,B {
}

super和this关键字

super:用来实现对父类成员的访问。

this:指向自己的引用。

示例:

class Animal {
  void eat() {
    System.out.println("animal : eat");
  }
}

class Dog extends Animal {
  void eat() {
    System.out.println("dog : eat");
  }
  void eatTest() {
    this.eat();   // this 调用自己的方法
    super.eat();  // super 调用父类方法
  }
}

public class Test {
  public static void main(String[] args) {
    Animal a = new Animal();
    a.eat();
    Dog d = new Dog();
    d.eatTest();
  }
}

final关键字

如果修饰类,则表示类不能被继承。如果修饰方法,则表示方法不能被子类重写。

重写与重载

重写与重载的区别可以通过下面这张图来看:

Java高级应用与开发答案 java高级编程_java_03

重写就是子类覆盖父类,方法名和参数都一样:

Java高级应用与开发答案 java高级编程_编程语言_04

重载就是在一个类里面的多个方法,方法名相同,参数不同。调用时根据入参匹配到不同的方法:

Java高级应用与开发答案 java高级编程_编程语言_05

多态

多态是同一个行为具有多个不同表现形式或形态的能力。重写可以看做是父类和子类之间多态性的一种表现(重载可以理解成多态的具体表现形式),如图所示:

Java高级应用与开发答案 java高级编程_抽象类_06

class Shape {
    void draw() {}
}

class Circle extends Shape {
    void draw() {
        System.out.println("Circle.draw()");
    }
}

class Square extends Shape {
    void draw() {
        System.out.println("Square.draw()");
    }
}

class Triangle extends Shape {
    void draw() {
        System.out.println("Triangle.draw()");
    }
}

多态存在有三个必要条件:

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

多态有三种实现方式:

  1. 重写
  2. 接口
  3. 抽象类和抽象方法

抽象类

抽象类更普通类的区别在于,它不能实例化对象,只能被继承使用。抽象类使用abstract关键字定义:

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number)
   {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public double computePay()
   {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + this.name
       + " " + this.address);
   }
   public String toString()
   {
      return name + " " + address + " " + number;
   }
   public String getName()
   {
      return name;
   }
   public String getAddress()
   {
      return address;
   }
   public void setAddress(String newAddress)
   {
      address = newAddress;
   }
   public int getNumber()
   {
     return number;
   }
}

抽象方法

抽象类里面既可以定义普通方法,也可以定义抽象方法:

public abstract class Employee
{
   private String name;
   private String address;
   private int number;

   public abstract double computePay();
}

抽象方法也是通过abstract关键字定义,只有方法名,没有方法体(方法名后面是分号而不是花括号),具体实现由它的子类确定。

抽象方法最终必须被重写了才能在实例化对象中使用。如果一个类继承了带有抽象方法的抽象类,那么这个类要么也是抽象类,要么就必须重写抽象方法。

接口

接口不是类,它们属于不同的概念。接口通过interface关键字来定义:

public interface Animal {
   public void eat();
   public void travel();
}
  • 接口和接口中的方法是隐式抽象的,不必使用abstract关键字。
  • 接口中的方法都是public

类使用implements关键字实现接口:

public class MammalInt implements Animal{

   public void eat(){
      System.out.println("Mammal eats");
   }

   public void travel(){
      System.out.println("Mammal travels");
   } 

   public int noOfLegs(){
      return 0;
   }

   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

类必须实现接口里面的所有方法,否则会编译失败。只有抽象类才可以不实现接口的方法。

一个接口能继承另一个接口,接口的继承也是使用extends关键字:

// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

// 文件名: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

并且接口支持多继承:

public interface Hockey extends Sports, Event

实现了子接口的类,需要同时实现所有父接口中的方法。

接口里面也可以没有方法:

package java.util;
public interface EventListener
{}

它的主要目的是:

  1. 建立一个公共的父接口。
  2. 让实现它的类属于一个特定的类型。

枚举

枚举是一种特殊的类,一般用来表示一组常量。枚举使用enum关键字来定义,常量使用逗号,分隔:

enum Color
{
    RED, GREEN, BLUE;
}
 
public class Test
{
    // 执行输出结果
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}

枚举也可以声明在内部类中:

public class Test
{
    enum Color
    {
        RED, GREEN, BLUE;
    }
 
    // 执行输出结果
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}

枚举可以使用for语句遍历:

enum Color
{
    RED, GREEN, BLUE;
}
public class MyClass {
  public static void main(String[] args) {
    for (Color myVar : Color.values()) {
      System.out.println(myVar);
    }
  }
}

也可以用在switch语句中:

enum Color
{
    RED, GREEN, BLUE;
}
public class MyClass {
  public static void main(String[] args) {
    Color myVar = Color.BLUE;

    switch(myVar) {
      case RED:
        System.out.println("红色");
        break;
      case GREEN:
         System.out.println("绿色");
        break;
      case BLUE:
        System.out.println("蓝色");
        break;
    }
  }
}

enum定义的枚举默认继承了java.lang.Enum类,具有3个方法:

  • values(),返回枚举中所有常量。
  • ordinal(),返回常量的索引。
  • valueOf(),返回指定字符串值的常量。
enum Color
{
    RED, GREEN, BLUE;
}
 
public class Test
{
    public static void main(String[] args)
    {
        // 调用 values()
        Color[] arr = Color.values();
 
        // 迭代枚举
        for (Color col : arr)
        {
            // 查看索引
            System.out.println(col + " at index " + col.ordinal());
        }
 
        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
        System.out.println(Color.valueOf("RED"));
    }
}

枚举跟普通类一样可以定义变量、方法和构造函数:

enum Color
{
    RED, GREEN, BLUE;
 
    // 构造函数
    private Color()
    {
        System.out.println("Constructor called for : " + this.toString());
    }
 
    public void colorInfo()
    {
        System.out.println("Universal Color");
    }
}
 
public class Test
{    
    // 输出
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
        c1.colorInfo();
    }
}

输出:

Constructor called for : RED
Constructor called for : GREEN
Constructor called for : BLUE
RED
Universal Color

包可以理解为类的目录,使用package关键字定义:

package com.runoob;
public class Runoob {
      
}

一个公司一般使用它互联网域名的倒序形式来作为它的包名,比如runoob.com,所有的包名都以com.runoob开头。

同一个包中的类可以直接访问,而访问不同的包需要先import。

//导入包下所有类
import payroll.*;
//导入包下某个类
import payroll.Employee;

集合

Java高级应用与开发答案 java高级编程_编程语言_07

集合(Collections)和数组(Arrays)的区别:

  • 长度区别:数组固定;集合可变。
  • 内容区别:数组既可以是基本类型,也可以是引用类型;集合只能是引用类型。
  • 存储类型:数组只能存储一种类型;集合可以存储不同类型(但一般也只存储一种类型)

集合中只能使用基本类型的包装类:

Java高级应用与开发答案 java高级编程_hashmap_08

集合主要包括两种类型的容器:Collection和Map,Collection是元素集合,Map是键值对。

集合有3个层次:

Java高级应用与开发答案 java高级编程_编程语言_09

接口代表集合的抽象数据类型,我们重点关注实现类和算法,尤其是4种常用实现类:ArrayList、LinkedList、HashSet、HashMap。

ArrayList

ArrayList相当于可以动态修改的数组。它继承了AbstractList,并实现了List接口:

Java高级应用与开发答案 java高级编程_java_10

定义

import java.util.ArrayList; // 引入 ArrayList 类

ArrayList<E> objectName = new ArrayList<>();  // 初始化

添加元素

使用add()方法:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites);
    }
}

访问元素

使用get()方法:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites.get(1));  // 访问第二个元素
    }
}

修改元素

使用set()方法:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        sites.set(2, "Wiki"); // 第一个参数为索引位置,第二个为要修改的值
        System.out.println(sites);
    }
}

删除元素

使用remove()方法:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        sites.remove(3); // 删除第四个元素
        System.out.println(sites);
    }
}

计算大小

使用size()方法:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites.size());
    }
}

迭代遍历

for循环:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        for (int i = 0; i < sites.size(); i++) {
            System.out.println(sites.get(i));
        }
    }
}

for-each语句:

import java.util.ArrayList;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        for (String i : sites) {
            System.out.println(i);
        }
    }
}

排序

使用Collections.sort()方法:

import java.util.ArrayList;
import java.util.Collections;  // 引入 Collections 类

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Taobao");
        sites.add("Wiki");
        sites.add("Runoob");
        sites.add("Weibo");
        sites.add("Google");
        Collections.sort(sites);  // 字母排序
        for (String i : sites) {
            System.out.println(i);
        }
    }
}

LinkedList

LinkedList是链表,分为单向链表和双向链表。

单向链表包含2个值,①当前节点的值,②下一个节点的链接:

Java高级应用与开发答案 java高级编程_Java高级应用与开发答案_11

双向链表包含3个值,①当前节点的值,②向前的节点链接,③向后的节点链接:

Java高级应用与开发答案 java高级编程_Java高级应用与开发答案_12

与ArrayList相比,LinkedList的增加和删除的效率更高,而修改和查找的效率更低。

快速记忆法:

增删:LinkedList

改查:ArrayList

LinkedList继承了AbstractSequentialList,实现了很多接口:

Java高级应用与开发答案 java高级编程_Java高级应用与开发答案_13

定义

// 引入 LinkedList 类
import java.util.LinkedList; 

LinkedList<E> list = new LinkedList<E>();   // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表

添加元素

import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        System.out.println(sites);
    }
}

在列表开头添加元素

使用addFirst()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

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);
    }
}

在列表结尾添加元素

使用addLast()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        // 使用 addLast() 在尾部添加元素
        sites.addLast("Wiki");
        System.out.println(sites);
    }
}

在列表开头移除元素

使用removeFirst()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 removeFirst() 移除头部元素
        sites.removeFirst();
        System.out.println(sites);
    }
}

在列表结果移除元素

使用removeLast()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 removeLast() 移除尾部元素
        sites.removeLast();
        System.out.println(sites);
    }
}

获取列表开头的元素

使用getFirst()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 getFirst() 获取头部元素
        System.out.println(sites.getFirst());
    }
}

获取列表结尾的元素

使用getLast()方法:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    public static void main(String[] args) {
        LinkedList<String> sites = new LinkedList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Weibo");
        // 使用 getLast() 获取尾部元素
        System.out.println(sites.getLast());
    }
}

迭代元素

可以使用for循环:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    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 (int size = sites.size(), i = 0; i < size; i++) {
            System.out.println(sites.get(i));
        }
    }
}

也可以使用for-each语句:

// 引入 LinkedList 类
import java.util.LinkedList;

public class RunoobTest {
    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);
        }
    }
}

HashMap

HashMap叫做哈希表,相当于键值对(key-value)的字典。它继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口:

Java高级应用与开发答案 java高级编程_java_14

定义

import java.util.HashMap; // 引入 HashMap 类

HashMap<Integer, String> Sites = new HashMap<>();

HashMap中只能使用基本类型的包装类,因为HashMap也是集合一种,在集合中只能使用包装类。

添加元素

使用put()方法:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites);
    }
}

访问元素

使用get()方法:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites.get(3));
    }
}

删除元素

使用remove()方法:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        Sites.remove(4);
        System.out.println(Sites);
    }
}

删除所有键值对

使用clear()方法:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        Sites.clear();
        System.out.println(Sites);
    }
}

计算大小

使用size()方法:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites.size());
    }
}

迭代

推荐使用entrySet:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
	System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue())
}

也可以用其他方式:

// 引入 HashMap 类      
import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        // 输出 key 和 value
        for (Integer i : Sites.keySet()) {
            System.out.println("key: " + i + " value: " + Sites.get(i));
        }
        // 返回所有 value 值
        for(String value: Sites.values()) {
          // 输出每一个value
          System.out.print(value + ", ");
        }
    }
}

HashSet

HashSet是一个不允许有重复元素的集合。它实现了Set接口:

Java高级应用与开发答案 java高级编程_Java高级应用与开发答案_15

定义

import java.util.HashSet; // 引入 HashSet 类

HashSet<String> sites = new HashSet<String>();

添加元素

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");  // 重复的元素不会被添加
        System.out.println(sites);
    }
}

判断元素是否存在

使用contains()方法:

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");  // 重复的元素不会被添加
        System.out.println(sites.contains("Taobao"));
    }
}

删除元素

使用remove()方法:

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        sites.remove("Taobao");  // 删除元素,删除成功返回 true,否则为 false
        System.out.println(sites);
    }
}

删除所有元素

使用clear()方法:

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        sites.clear();  
        System.out.println(sites);
    }
}

计算大小

使用size()方法:

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        System.out.println(sites.size());  
    }
}

迭代

使用for-each语句:

// 引入 HashSet 类      
import java.util.HashSet;

public class RunoobTest {
    public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");     // 重复的元素不会被添加
        for (String i : sites) {
            System.out.println(i);
        }
    }
}

Iterator

Iterator是迭代器,可以用来迭代ArrayList等集合。迭代器主要有3个方法:

  • next():返回下一个元素,并更新迭代器状态。
  • hasNext():检查是否还有元素。
  • remove():删除元素。

获取集合的迭代器

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;

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

        // 创建集合
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");

        // 获取迭代器
        Iterator<String> it = sites.iterator();

        // 输出集合中的第一个元素
        System.out.println(it.next());
    }
}

迭代器遍历集合

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;

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

        // 创建集合
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");

        // 获取迭代器
        Iterator<String> it = sites.iterator();

        // 输出集合中的所有元素
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

删除元素

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;

public class RunoobTest {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<Integer>();
        numbers.add(12);
        numbers.add(8);
        numbers.add(2);
        numbers.add(23);
        Iterator<Integer> it = numbers.iterator();
        while(it.hasNext()) {
            Integer i = it.next();
            if(i < 10) {  
                it.remove();  // 删除小于 10 的元素
            }
        }
        System.out.println(numbers);
    }
}

泛型

泛型可以理解为通用类型,不是具体某个类型,而是泛指某些类型。

Java中的泛型标记符如下所示:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • - 表示不确定的 java 类型

示例:

public class GenericMethodTest {
    // 泛型方法 printArray                         
    public static <E> void printArray(E[] inputArray) {
        // 输出数组元素            
        for (E element : inputArray) {
            System.out.printf("%s ", element);
        }
        System.out.println();
    }

    public static void main(String args[]) {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = {1, 2, 3, 4, 5};
        Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};
        Character[] charArray = {'H', 'E', 'L', 'L', 'O'};

        System.out.println("整型数组元素为:");
        printArray(intArray); // 传递一个整型数组

        System.out.println("\n双精度型数组元素为:");
        printArray(doubleArray); // 传递一个双精度型数组

        System.out.println("\n字符型数组元素为:");
        printArray(charArray); // 传递一个字符型数组
    }
}

其中<E>放在方法前表明这是一个泛型方法。可以通过extends限制类型的范围:

public class MaximumTest
{
   // 比较三个值并返回最大值
   //java.lang.Comparable是个接口,包含一个compareTo()方法
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                     
      T max = x; // 假设x是初始最大值
      if ( y.compareTo( max ) > 0 ){
         max = y; //y 更大
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // 现在 z 更大           
      }
      return max; // 返回最大对象
   }
   public static void main( String args[] )
   {
      System.out.printf( "%d, %d 和 %d 中最大的数为 %d\n\n",
                   3, 4, 5, maximum( 3, 4, 5 ) );
 
      System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f\n\n",
                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );
 
      System.out.printf( "%s, %s 和 %s 中最大的数为 %s\n","pear",
         "apple", "orange", maximum( "pear", "apple", "orange" ) );
   }
}

除了泛型泛型方法,还可以定义泛型类

public class Box<T> {
   
  private T t;
 
  public void add(T t) {
    this.t = t;
  }
 
  public T get() {
    return t;
  }
 
  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String> stringBox = new Box<String>();
 
    integerBox.add(new Integer(10));
    stringBox.add(new String("菜鸟教程"));
 
    System.out.printf("整型值为 :%d\n\n", integerBox.get());
    System.out.printf("字符串为 :%s\n", stringBox.get());
  }
}

?是类型通配符,比如List<?>在逻辑上是List<String>List<Integer>等的父类:

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}

?也可以通过extends关键字来限定类型范围:

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        //getUperNumber(name);//1
        getUperNumber(age);//2
        getUperNumber(number);//3
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
   
    //只接受Number及其子类
   public static void getUperNumber(List<? extends Number> data) {
          System.out.println("data :" + data.get(0));
       }
}

List<? extends Number表示只接受Number及其子类(指定上限)。此外还能通过List<? super Number>来表示只能接受Number及其父类(指定下限)。

参考资料:

Java面向对象 https://www.runoob.com/java/java-inheritance.html

Java高级编程 https://www.runoob.com/java/java-data-structures.html