Summary of Java knowledge points "Effort Part 1"

Small chat : This article mainly edits small details or knowledge supplements that Xiaobai feels are important and easy to forget Javawhen . Thinking that it will be very helpful for learning and using Javait , I will record it a little bit. The knowledge points with more content will be written in this column, so here are all small tipsones.

The entire Java language part, I will divide it into "Basic Articles", "Efforts" and "Supplementary Articles", and the supplementary articles may also be updated from time to time~ This article is "Efforts Part 1".

All sections so far:

Summary of Java knowledge points "Basic"

Summary of Java knowledge points "Effort Part 1"

Summary of Java knowledge points "Effort Part II"


1. Object class

The java.lang.Object class is the root class in the Java language, that is, the parent class of all classes. All methods described in it can be used by subclasses. When an object is instantiated, the final parent class is Object. If a class does not specify a parent class, it inherits from the Object class by default.

  • all methods
ModifierandType Method and Description
protected Object clone() Creates and returns a copy of this object.
boolean equals(Object obj) Indicates whether some other object is equal to this.
protected void finalize() The garbage collector is invoked on an object when garbage collection determines that there are no longer references to the object.
class<?> getClass() Returns the runtime class of this Object .
int hashCode() Returns the hash code value of the object.
void notify() Wake up a single thread that is waiting on an object monitor.
void notifyAll() Wakes up all threads that are waiting on the object's monitor.
String toString() Returns a string representation of the object.
void wait() Causes the current thread to wait until another thread calls the object's notify() method or notifyAll() method.
void wait(long timeout) Causes the current thread to wait until another thread calls the notify() method or the object's notifyAll() method, or until the specified time has elapsed.
void wait(longtimeout,intnanos) Causes the current thread to wait until another thread calls the object's notify() method or notifyAll() method, or some other thread interrupts the current thread, or until a certain amount of real time.

2. System class

  • common method
method explain
static void exit(int status) This method is used to terminate the currently running Java virtual machine, where the parameter status indicates the status code, if the status code is not 0, it means abnormal termination
static void gc() Run the garbage collector and recycle garbage
static native long currentTimeMillis() Returns the current time in milliseconds
static void arraycopy(0bject src, int srcPos, 0bject dest, int destPos, int length) Copy from the specified source array referenced by src to the array referenced by dest, copying starts from the specified position and ends at the specified position of the target array (the copy method of many types of arrays will call System.arraycopy)
static Properties getProperties() Get the current system properties
static String getProperty(String key) Get the system property described by the specified key
  • Code usage example
import java.util.Properties;

public class SystemDemo {
    
    
	public static void main(String[] args) {
    
    
        // 1. static void exit(int status) 			退出jvm,一般情况下状态传0,表示正常终止
		/*
		for(int i = 1; i < 10; i ++) {
			if(i == 5) {
				System.exit(0);
			}
			System.out.println(i);
		}
		*/
		
		//2. static void gc()						运行垃圾回收器,并对垃圾进行回收
		System.gc();
		
		//3. static native long currentTimeMillis()	返回以毫秒为单位的当前时间
		long strat = System.currentTimeMillis();
		for(int i = 1; i <= 100; i++) {
    
    
			System.out.println(i);
		}
		long end = System.currentTimeMillis();
		System.out.println(end - strat);
		
		//4. static void arraycopy(0bject src, int srcPos, 0bject dest, int destPos, int length)
		/*
			Object src: 要复制的源数组
			int srcPos: 源数组中的开始索引位置
			Object dest: 要复制的目标数组
			int destPos:目标数组的开始接受的索引位置
			int length: 复制的个数
		 */
		int[] src = {
    
    1, 2, 3, 4, 5};
		int[] dest = {
    
    6, 7, 8, 9, 10};
		System.arraycopy(src, 1, dest, 2, 3);
		for(int i = 0; i < dest.length; i ++) {
    
    
			System.out.print(dest[i] + " ");
		}
		System.out.println();	
        
		//5. static Properties getProperties()		 取得当前的系统属性
		Properties prop = System.getProperties();
		//System.out.println(prop);
		
		//6. static String getProperty(String key)	获取指定键描述的系统属性	
		String os = System.getProperty("os.name");
		System.out.println(os);
	}		
}

输出
1~100
2
6 7 2 3 4 
Windows 10

3. Common methods of String

method explain
judgment function
boolean equals(String s); Determine whether two strings are the same, case sensitive
boolean equalsIgnoreCase(String s); Determine whether two strings are equal, case insensitive
boolean startsWith(String s); Determine whether the current string starts with the passed in
boolean endsWtih(String s); Determine whether the current string ends with the incoming string
boolean contains(String s); Determine whether the current string contains the incoming string
boolean isEmpty(); Check if the string is empty
get function
int length(); Get the length of a string
char charAt(int index); Get the character at the specified index
int index0f(String s); Get the index position of the first occurrence of the incoming string in the current string
int lastIndex0f(String s); Get the position of the last occurrence of the incoming string in the current string
String concat(String s); concatenate string
String substring(int index); Extract a string. Start at index position, default to end
String substring(int start, int end); 截取字符串。从指定索引位置开始,到默认索引位置结束(包含头,不包含尾)
转换功能
char[] toCharArray(); 将字符串转换成字符数组
byte[] getBytes(); 将字符串转换成字节数组
String toUpperCase(); 将字符串转换成大写
String toLowerCase(); 将字符串转换成小写
String value0f(int i); 将数字转换成字符串
其他功能
String[] split(String regex); 将字符串按照指定规则进行切割,返回字符串数组
String trim(); 去除字符串两端的空格

4. String、StringBuffer和StringBuilder

  • StringBuffer、StringBuilder和String相同之处

    • 都是操作字符串,但本质是字符数组,所以类方法实际操作的是char数组。
    • StringBuffer、StringBuilder的使用和String没什么区别,只不过初始化时需要new对象,而String可以直接声明复制,很像基本类型。
    • 它们的类都使用了final修饰。
  • StringBuffer、StringBuilder和String不同之处

    • String的本质char数组是类中私有成员变量,使用了final关键字修饰,而StringBuffer、StringBuilder是通过调用父类方法初始化char数组值的,没有使用final修饰。(关于final的作用《基础篇》有讲)因此,String每次修改时都会创建一个新的char数组返回,相比性能是最差的,不过用起来很方便。

    • StringBuffer、StringBuilder除了能使用String的方法外,还有属于自己的方法,但是String的方法基本够用了。

      方法 解释
      StringBuffer/StringBuilder append(char c) 添加字符到StringBuffer对象中末尾
      StringBuffer/StringBuilder insert(int offset, String str); 在StringBuffer对象中的offset位置插入字符串str
      StringBuffer/StringBuilder deleteCharAt(int index); 移除StringBuffer对象在指定位置的字符
      StringBuffer/StringBuilder delete(int start, int end); 删除StringBuffer对象中指定范围的字符或字符串
      StrinfBuffer/StringBuilder replace(int start, int end, String s); 将StringBuffer对象在指定范围的字符或字符串用新的字符串s进行代替
      void setCharAt(int index, char ch); 修改指定位置index处的字符
      stringBuffer/StringBuilder reverse() 将此StringBuffer对象用其反转形式取代
  • StringBuffer和StringBuilder相同之处

    • 都是操作字符串,有很多使用相同的方法操作字符串,只不过StringBuffer的方法多一点。
    • 本质操作的都是char[],是继承的父类AbstractStringBuilder的成员变量char[] value,顺便说String的char数组是本类,没有父类。
  • StringBuffer和StringBuilder不同之处

    • 线程安全: StringBufferd 支持并发操作,线性安全的,适合多线程中使用。StringBuilder 不支持并发操作,线性不安全的,不适合多线程中使用。因为 StringBuffer 的所有公开方法都是直接 synchronized 修饰或间接调用被 synchronized 修饰的方法(比如 insert 和 index),而 StringBuilder 并没有 synchronized 修饰。
    • 缓冲区优化,toString()原理: 输出 StringBuffer 和 StringBuilder 对象时会调用 toString 方法返回一个String 对象,StringBuilder是直接返回一个 new String(xxx)。
      而 StringBuffer 有一个私有成员变量 char[] 名叫 toStringCache,是做缓存用的,ToString() 时会把继承父类的 char 数组名叫 value 的值赋给 toStringCache(顺便一提,这里复制 char 数组的方法最底层使用的就是 System.arraycopy),这里其实会做一个为空的判断,toStringCache 为空的话就会给它值然后返回。因为 StringBuffer 的字符串操作方法被调用时都会先把 toStringCache 清空,因为对数据操作的话就可能会改变 value 字符数组的值,toStringCache 是作为缓存的需要被重置更新,如果使用 toString 方法之前没有调用操作字符串的方法 toStringCache 自然不会被清空,就可以直接返回。总结来说,value 是用来操作的,toStringCache 是用来返回结果的。
    • 性能: 因为加了 synchronized 锁的缘故,所以StringBuffer稍微会被影响一点性能,平均速度性能比较:StringBuilder > StringBuffer > String
  • StringBuffer和StringBuilder 建议使用

    • 不涉及多线程,简单的赋值、取操作使用String就够了。
    • 单线程要进行String操作使用StringBuilder,多线程要保证安全需要使用StringBuffer。

5. 集合

集合按照其存储结构可以分为两大类,分别是单列集合 java.util.Collection 和双列集合 java.util.Map

  • 集合体系图(重要)
    在这里插入图片描述

  • Collection 单列集合

    • java.util.List :元素有序、元素可重复
      • java.util.ArrayList :动态数组的数据结构
      • java.util.LinkedList:双向链表结构,也可当作堆栈、队列、双端队列的数据结构
      • java.util.Vector:动态数组的数据结构
    • java.util.Set :元素无序,而且不可重复
      • java.util.HashSet :基于 HashMap 实现的,底层采⽤ HashMap 来保存元素
      • java.util.LinkedHashSet :是 HashSet 的⼦类,基于 LinkedHashMap 实现的
      • java.util.TreeSet :红⿊树(⾃平衡的排序⼆叉树)
  • Map 双列集合

    • HashMap: JDK1.8 之前 数组+链表;JDK1.8 以后 数组+链表+红黑树
    • LinkedHashMap: 是 HashMap 的⼦类,在其结构基础上增加了一条双向链表
    • Hashtable:数组+链表,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突⽽存在的
    • TreeMap:红⿊树(⾃平衡的排序⼆叉树)

6. ArrayList、LinkedList和Vector

  • ArrayList 和 LinkedList区别

其实区别都是根据他们的底层数据结构来的,所以知道底层结构的区别和作用就很容易理解了。(Vector底层也是数组,和LinkedList差不多)

  1. 效率不同
    ArrayList 的查找效率高;LinkedList 的增删操作效率高。

    前者因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找,效率低;
    后者因为 ArrayList 是数组,在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动,效率低。

  2. 自由性不同

    ArrayList 自由性较低,因为它需要手动的设置固定大小的容量,创建、添加数据,调用下标进行使用比较方便;
    LinkedList 自由性较高,能够动态的随数据量的变化而变化,公共方法与ArrayList有些不同,使用比较复杂。

  3. 空间消耗不同

    ArrayList 主要空间开销在于需要在lList列表预留一定空间;
    而 LinkList 主要空间开销在于需要存储结点信息以及结点指针信息。

  • List 和 Vector 的区别
  1. 线程安全

    Vector 的方法使用了 synchronized 同步,多线程安全。(但是Vector较老,有个比它更好用的线程安全类:CopyOnWriteArrayList)
    List 速度优势,没有同步,线程不安全,单线程下使用。


7. Queue 和 Stack(队列、堆栈)

属于单列集合的体系

  • 特点

    • Queue 队列先进先出(可以看做水上乐园的滑梯)
    • Stack 堆栈先进后出(可以看做枪的子弹夹)
  • 结构

    • Queue 是接口,继承 Collection 接口
    • Stack 是类,继承了 Vector 接口
  • Queue 本身所有方法

    方法 说明
    add() 在不违反容量限制的情况下,如果可以立即将指定元素插入到此队列中,成功返回true;为空,则抛 IllegalStateException。
    offer() 在不违反容量限制的情况下,将指定的元素插入到此队列中成功返回 true;否则返回 false。在使用容量受限的队列时,此方法通常比添加方法更可取,因为 add() 只能通过抛出异常来插入元素。
    remove() 获取并移除此队列的头,如果此队列为空,则抛出NoSuchElementException异常
    poll() 获取并移除此队列的头,如果此队列为空,则返回 null
    element() 检索但不删除此队列的头。如果此队列为空,则抛出NoSuchElementException异常
    peek() 检索但不删除此队列的头,如果此队列为空,则返回 null
  • Stack 本身所有方法

    方法 说明
    push() 入栈,将一个元素放到堆栈的顶部
    pop() 出栈,移除堆栈顶部的元素,并返回该对象作为此函数的值。如果为空,抛出:EmptyStackException异常
    peek() 查看位于堆栈顶部的元素并返回,而不将其从堆栈中移除。如果为空,抛出:EmptyStackException异常
    empty() 判断此堆栈是否为空,不为空返回true,否则返回false
    search(Object 0) 堆栈上最上面的元素被认为距离为1,返回元素在堆栈上的基于1的位置。不存在该元素则返回 -1

8. HashSet、LinkedHashSet、TreeSet

Set 最重要的特性就是元素不可重复,子类的功能特点区别和List差不多。因为底层是 HsahMap,讲Map的时候再讲HashMap的实现底层。

  • HashSet:不可重复,无序

  • LinkedHashSet:无索引、不可以存储重复元素、可以保证存取顺序

  • TreeSet:存储不重复,会自动给元素排序,默认按字典序排序;可以自定义排序:自然排序和定制排序;因为有序的特性,有许多特有方法,可以用来操作集合

    TreeSet特有方法方法 解释
    Object first() 返回TreeSet集合的首个元素
    Object last() 返回TreeSet集合的最后一个元素
    Object lower(Object o) 返回TreeSet集合中小于给定元素的最大元素,如果没有返回null
    Object floor(Object o) 返回TreeSet集合中小于或等于给定元素的最大元素,如果没有返回null
    Object higher(Object o) 返回TreeSet集合中大于给定元素的最小元素,如果没有返回null
    Object ceiling(Object o) 返回TreeSet集合中大于或等于给定元素的最小元素,如果没有返回null
    Object pollFirst() 移除并返回集合的第一个元素
    Object pollLast() 移除并返回集合的最后一个元素
  • Set 如何实现不可重复?

是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashCodeequals 方法。如果我们往Set集合中存放自定义的对象,比如 Student 类,那么保证其唯一,就必须复写 hashCodeequals 方法建立属于当前对象的比较方式。在Java中,一些基本数据包装类、String类等 都已经默认写了 hashCode()equals() 方法。

  • Set 无序真的是无序?无序的含义

⽆序性是指存储的数据在底层数组中并⾮按照数组索引的顺序添加 ,⽽是根据数据的哈希值决定的。


9. TreeSet 的自定义排序

  • 实现 Comparable 接口 —— 自然排序

要求存储的元素类必须实现 Comparable 接口,并重写 compareTo() 方法。要输出的话可以重写 toString() 方法

特点:

  • 元素类本身实现 Comparable 接口
  • 依赖 compareTo() 方法的实现
  • 实现 Comparable 接口排序则比较单一,不利于后续改进

代码示例:

import java.util.TreeSet;

class Person implements Comparable<Person> {
    
    
    private String name;
    private int age;

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

    @Override
    public int compareTo(Person o) {
    
    
        //定义比较方式,先比较年龄age,再比较名称name
        if (this.age > o.age) {
    
    		//从小到大
            return 1;
        }
        else if (this.age == o.age) {
    
    
            return this.name.compareTo(o.name);
        }
        return -1;
    }

    @Override
    public String toString() {
    
    
        return name + ":" + age;
    }
}

public class TreeSet自然排序 {
    
    
    public static void main(String[] args) {
    
    
        Person stu1 = new Person("鸢一折纸", 16);
        Person stu2 = new Person("时崎狂三", 17);
        Person stu3 = new Person("夜刀神十香", 17);
        Person stu4 = new Person("崇宫真那", 16);
        Person stu5 = new Person("鸢一折纸", 16);
        TreeSet<Person> treeSet = new TreeSet<>();
        treeSet.add(stu1);
        treeSet.add(stu2);
        treeSet.add(stu3);
        treeSet.add(stu4);
        treeSet.add(stu5);
        System.out.println(treeSet);

    }
}

输出
[崇宫真那:16, 鸢一折纸:16, 夜刀神十香:17, 时崎狂三:17]
  • 实现 Comparator 接口 —— 定制排序

要求自定义一个比较器,该比较器必须实现 Comparator 接口,并重写 compare() 方法,然后将该比较器作为参数传入集合的有参构造。

代码举例:

import java.util.Comparator;
import java.util.TreeSet;

class Man {
    
    
    private String name;
    private int age;

    public Man() {
    
    
    }

    public Man(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;
    }

    @Override
    public String toString() {
    
    
        return "Man{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


public class TrrSet定制排序 {
    
    
    public static void main(String[] args) {
    
    
        Man stu1 = new Man("鸢一折纸", 16);
        Man stu2 = new Man("时崎狂三", 17);
        Man stu3 = new Man("夜刀神十香", 17);
        Man stu4 = new Man("崇宫真那", 16);
        Man stu5 = new Man("鸢一折纸", 16);
        TreeSet<Man> tr = new TreeSet<>(new Comparator<Man>() {
    
    
            @Override
            public int compare(Man o1, Man o2) {
    
    
                //定义比较方式,先比较年龄age,再比较名称name
                if (o1.getAge() > o2.getAge()) {
    
    
                    return 1;
                }
                else if (o1.getAge() == o2.getAge()) {
    
    
                    return o1.getName().compareTo(o2.getName());
                }
                return -1;
            }
        });
        tr.add(stu1);
        tr.add(stu2);
        tr.add(stu3);
        tr.add(stu4);
        tr.add(stu5);
        tr.forEach((man) -> System.out.println(man));
    }
}

输出
Man{
    
    name='崇宫真那', age=16}
Man{
    
    name='鸢一折纸', age=16}
Man{
    
    name='夜刀神十香', age=17}
Man{
    
    name='时崎狂三', age=17}
  • 简述Comparable和Comparator的区别

Comparable: 强行对实现它的每个类的对象进行整体排序,固定死板。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

Comparator: 强行对某个对象进行整体排序,灵活的排序,即用即制定。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。


10. Collections工具类

它包含有各种有关集合操作的静态多态方法,用于实现对各种集合的搜索、排序、线程安全化等操作。

  • 常用方法
方法 解释
static boolean addAll(Collection<? super T> C, T… elements) 将所有指定元素添加到指定集合C中
static void reverse(List list) 反转指定List集合中元素的顺序
static void shuffle(List list) 对List集合中的元素进行随机排序,打乱集合顺序
public static void sort(List list) 根据元素的自然顺序对List集合中的元素进行排序
public static void sort(List list,Comparator<? super T>) 将集合中元素按照指定规则排序
static void swap(List list, int i, int j) 将指定List集合中角标i处元素和j处元素进行交换
static int binarySearch(List list ,0bject key) 使用二分法搜索指定对象在List集合中的索引,查找的List集合中的元素必须是有序的
static Object max(Collection col) 根据元素的自然顺序,返回给定集合中最大的元素
static Object min(Collection col) 根据元素的自然顺序,返回给定集合中最小的元素
static boolean replaceAll(List list,Object oldVal,Object newVal) 用一个新值newVal替换List集合中所有的旧值oldVal
  • 代码演示
import java.util.ArrayList;
import java.util.Collections;

public class CollectionsDemo {
    
    
	public static void main(String[] args) {
    
    
		
		ArrayList<String> list = new ArrayList<String>();
		
		//static <T> boolean addAll(Collection<? super T> C, T... elements)将所有指定元素添加到指定集合C中
		Collections.addAll(list, "aaa", "ccc", "aaa", "ddd", "bbb");
		System.out.println(list);
		
		//static void reverse(List list) 反转指定List集合中元素的顺序
		Collections.reverse(list);
		System.out.println(list);
		
		//static void shuffle(List list)对List集合中的元素进行随机排序
		Collections.shuffle(list);
		System.out.println(list);

		
		//static void swap(List list, int i, int j)将指定List集合中角标i处元素和j处元素进行交换
		Collections.swap(list, 0, list.size() - 1);
		System.out.println(list);
		
		//static void sort(List list) 根据元素的自然顺序对List集合中的元素进行排序
		Collections.sort(list);
		System.out.println(list);
		
		//static int binarySearch(List list ,0bject key)使用二分法搜索指定对象在List集合中的索引,查找的List集合中的元素必须是有序的	
		int num = Collections.binarySearch(list, "bbb");
		System.out.println(num);
		
		//static Object max(Collection col)根据元素的自然顺序,返回给定集合中最大的元素
		String arr = Collections.max(list);
		System.out.println(arr);
		
		//static Object min(Collection col)根据元素的自然顺序,返回给定集合中最小的元素
		String str = Collections.min(list);
		System.out.println(str);
				
		//static boolean replaceAll(List list,Object oldVal,Object newVal)用一个新值newVal替换List集合中所有的旧值oldVal
		boolean bool = Collections.replaceAll(list, "aaa", "xxx");	//所以相同的旧值元素
		System.out.println(bool);
		System.out.println(list);
	
	}
}

输出
[aaa, ccc, aaa, ddd, bbb]
[bbb, ddd, aaa, ccc, aaa]
[ddd, bbb, aaa, aaa, ccc]
[ccc, bbb, aaa, aaa, ddd]
[aaa, aaa, bbb, ccc, ddd]
2
ddd
aaa
true
[xxx, xxx, bbb, ccc, ddd]

11. Arrays数组工具类

  • 常用方法
方法 解释
void sort(); 对数组排序
String toString(0bject[]); 打印数组
int binarySearch(0bject[] a, Object key); 使用二分查找法获取指定元素在数组中出现的索引位置
int[] copyOfRange(int[] original, int from, int to); 复制数组元素到一个新数组中
void fill(0bject[] a, object val); 使用传入元素替换数组中所有的元素
  • 代码演示
import java.util.Arrays;

public class ArraysDemo {
    
    
	public static void main(String[] args) {
    
    		
		int [] arr = {
    
    10, 40 ,30 ,20 ,50};
		printArrays(arr);		//自定义方法:打印原位置数组元素
		String a = Arrays.toString(arr);
		System.out.println("a = " + a);
		System.out.println("地址值:" + arr);	//打印地址值
		
		//void sort();		对数组排序
		Arrays.sort(arr);
		System.out.println("排序后输出:" + Arrays.toString(arr));
			
		//int binarySearch(Object[] a, Object key);	使用二分查找法获取指定元素在数组中出现的索引位置
		int num = Arrays.binarySearch(arr, 30);
		System.out.println("元素30的索引是:" + num);	
		
		//int[] copyOfRange(int[] original, int from, int to);	复制(部分)数组元素到一个新数组中
		int [] copy = Arrays.copyOfRange(arr, 1, 8);	
		System.out.println(Arrays.toString(copy));	//超出索引的位置会补0
		
		//void fill(0bject[] a, object val);	使用传入元素替换数组中所有的元素
		Arrays.fill(arr, 6);
		System.out.println(Arrays.toString(arr));
	
	}

	private static void printArrays(int[] arr) {
    
    
		for(int str : arr) {
    
    
			System.out.print(str + " ");
		}
        System.out.println();
	}
}

输出
10 40 30 20 50 
a = [10, 40, 30, 20, 50]
地址值:[I@15db9742
排序后输出:[10, 20, 30, 40, 50]
元素30的索引是:2
[20, 30, 40, 50, 0, 0, 0]
[6, 6, 6, 6, 6]

12. Iterator迭代器

在程序开发中,经常需要遍历集合中的所有元素,而集合无索引的特性难以遍历。针对这种需求,JDK专门提供了一个 java.util.Iterator 接口。Iterator 接口也属于集合, 主要用于迭代访问(即遍历) Collection 中的元素,因此 Iterator 对象也被称为迭代器。

获取迭代器的方法 解释
public Iterator iterator() 获取集合对应的迭代器,用来遍历集合中的元素的
Iterator接口的常用方法 解释
public E next() 返回迭代的下一个元素
public boolean hasNext() 如果仍有元素可以迭代,则返回 true
  • 代码演示
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Iterator迭代器 {
    
    
    public static void main(String[] args) {
    
    
        Collection<String> str = new ArrayList<>();
        str.add("鸢一折纸");
        str.add("时崎狂三");
        str.add("夜刀神十香");

        Iterator<String> it = str.iterator();
        while(it.hasNext()) {
    
    
            System.out.println(it.next());
        }
        System.out.println("----------------------");
        //建议使用增强for(原理也是Iterator迭代器)
        for (String s : str) {
    
    
            System.out.println(s);
        }
    }
}

输出
鸢一折纸
时崎狂三
夜刀神十香
----------------------
鸢一折纸
时崎狂三
夜刀神十香
  • 迭代器的实现原理
  • 当遍历集合时,首先通过调用集合的 iterator() 方法获得迭代器对象,然后使用 hashNext() 方法判断集合中是否存在下一个元素,如果存在,则调用 next() 方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

  • 在调用 Iteratornext() 方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的 next() 方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用 next() 方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到 hasNext() 方法返回 false,表示到达了集合的末尾,终止对元素的遍历。


13. 增强for和foreach

  • 增强for循环

增强for循环(也称foreach循环)是 JDK1.5 以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个 Iterator 迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

新for循环必须有被遍历的目标。目标只能是Collection或者是数组。新式for仅仅作为遍历操作出现。

格式

for(元素的数据类型  变量 : Collection集合or数组){
     
      
  	//写操作代码
}

使用示例:

import java.util.ArrayList;
import java.util.Collection;

public class foreachDemo {
    
    
	public static void main(String[] args) {
    
    
		String [] arr = {
    
    "鸢一折纸", "本条二亚", "时崎狂三", "四糸乃", "五河琴里",
						"星空六喰", "七罪", "八舞耶俱矢&八舞夕弦", "诱宵美九", "夜刀神十香"	};
		for(String str : arr) {
    
    
			System.out.println(str);
		}
		System.out.println("=======================");
		
		//使用增强for循环遍历集合
		Collection<Integer> coll = new ArrayList<Integer>();
		coll.add(100);
		coll.add(200);
		coll.add(300);
		coll.add(400);
		for(Integer i : coll) {
    
    
			System.out.println(i);
			//coll.remove(200);		运行异常,不能使用增强for循环来删除元素
		}
	}
}

输出
鸢一折纸
本条二亚
时崎狂三
四糸乃
五河琴里
星空六喰
七罪
八舞耶俱矢&八舞夕弦
诱宵美九
夜刀神十香
=======================
100
200
300
400    
  • forEach

JDK8版本后的一个新的遍历方式,比增强for的更简便、更快

格式

集合(数组)名.forEach((泛型类型(可省略) 变量名) -> 执行语句);

代码演示:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class forEach {
    
    
    public static void main(String[] args) {
    
    
        Collection<String> coll = new ArrayList<>();
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");

        //JDK8版本后的forEach( )方法遍历集合
        coll.forEach((a) -> System.out.println(a));
        System.out.println("=================");

        //JDK8版本后的迭代器对象forEachRemaining( )方法遍历集合
        Iterator<String> it = coll.iterator();
        it.forEachRemaining((String a) -> {
    
    System.out.println(a);});
    }
}

输出
aaa
bbb
ccc
=================
aaa
bbb
ccc 

14. 泛型

泛型(generics)是 JDK 5 中引入的一个新特性,**“泛型” 意味着编写的代码可以被不同类型的对象所重用。**让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查。

泛型一般有三种使用方式:泛型类、泛型接口、泛型方法

可以在类或方法中预支地使用未知的类型,也可以限制集合容器内元素的种类,当没有指定泛型时,默认类型为Object类型。

  • 常用的通配符为: TEKV

    ? 表示不确定的 java 类型

    T (type) 表示具体的一个java类型

    K、V (key value) 分别代表java键值中的Key Value

    E (element) 代表 Element元素

  • 泛型类

  • 定义
修饰符 class 类名<代表泛型的变量> {
     
     }
  • 代码演示
class fruit<E>{
     
      
    public boolean delicious(E e){
     
      }
    public E name(int index){
     
      }
   	....
}
  • 什么时候确定泛型?

在创建对象的时候确定泛型

// 如果
fruit<String> list = new fruit<String>();
// 那么
class fruit<Integer> {
     
      
     public boolean delicious(String e) {
     
      }
     public String name(int index) {
     
      }
     ...
}
  • 使用举例
class MyGenericClass<MVP> {
     
     
	//没有MVP类型,在这里代表未知的一种数据类型,未来传递什么就是什么类型
	private MVP mvp;
    public void setMVP(MVP mvp) {
     
     
        this.mvp = mvp;
    }
    public MVP getMVP() {
     
     
        return mvp;
    }
}

public class GenericClassDemo {
     
     
  	public static void main(String[] args) {
     
     		 
         // 创建一个泛型为String的类
         MyGenericClass<String> my = new MyGenericClass<String>();    	
         // 调用setMVP
         my.setMVP("美国队长");
         // 调用getMVP
         String mvp = my.getMVP();
         System.out.println(mvp);
         //创建一个泛型为Integer的类
         MyGenericClass<Integer> my2 = new MyGenericClass<Integer>(); 
         my2.setMVP(123);   	  
         Integer mvp2 = my2.getMVP();
    }
}

输出
美国队长
  • 泛型方法

泛型方法 是在调用方法的时候指明泛型的具体类型。

修饰符 [static] <代表泛型的变量> 返回值类型 方法名(参数){
     
      }

修饰符与返回值类型中间的 泛型标识符 <T,E,…>,是 泛型方法的标志,只有这种格式声明的方法才是泛型方法。

泛型方法声明时的 泛型标识符 <T,E,…> 表示在方法可以使用声明的泛型类型。

与泛型类相同,泛型标识符可以是任意类型,常见的如T,E,K,V 等。

泛型方法可以声明为 static 的,并且与普通的静态方法是一样的。

  • 代码举例
public class MyGenericMethod {
     
     	  
    public <MVP> void show(MVP mvp) {
     
     
    	System.out.println(mvp.getClass());
    }
}		

//调用方法时,确定泛型的类型
public class GenericMethodDemo {
     
     
    public static void main(String[] args) {
     
     
        // 创建对象
        MyGenericMethod mm = new MyGenericMethod();
        // 演示看方法提示
        mm.show("aaa");
        mm.show(123);
        mm.show(12.45);
    }
}

输出
class java.lang.String
class java.lang.Integer
class java.lang.Double
  • 泛型接口
  • 定义
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){
     
     }
  • 代码演示
public interface MyGenericInterface<E> {
     
     
	public abstract void add(E e);
	public abstract E getE();  
}
  • 代码举例
public class MyImp1 implements MyGenericInterface<String> {
     
     
	@Override
    public void add(String e) {
     
     
        // 省略...
    }

	@Override
	public String getE() {
     
     
		return null;
	}
}

15. Map集合

之所以在讲单列集合后又讲迭代器、for遍历和泛型,是因为Map用得到。

  • 常用子类

    • HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。
    • LinkedHashMap<K,V>HashMap下有个子类 LinkedHashMap,存储数据采用的哈希表结构+链表结构。
    • **TreeMap<K, V>:**键值key唯一,会自动给元素排序,用 key 值默认按字典序排序
  • Map常用方法

方法 解释
public V put(K key, V value) 把指定的键与指定的值添加到Map集合中
int size() 返回Map集合键值对映射的个数
public V get(Object key) 返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回null
boolean containsKey(Object key) 查看Map集合中是否存在指定的键对象key
boolean containsValue(object value) 查看Map集合中是否存在指定的值对象value
public V remove(Object key) 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值
boolean remove(Object key , object value) 删除Map集合中键值映射同时匹配的元素(JDK 8新方法),返回删除结果
void clear() 清空整个Map集合中的键值映射元素
String replace(0bject key,object value) 将 Map集合中指定键对象Key所映射的值修改为value (JDK8 新方法)
遍历方法 解释
Set keySet() 以Set集合的形式返回Map集合中所有的键对象Key;
Collection values() 以Collection集合的形式返回Map集合中所有的值对象Value
Set<Map.Entry<Key,Value>>entrySet() 将Map集合转换为存储元素类型为Map的Set集合
void forEach(BiConsumer action) 通过传入一个函数式接口对Map集合元素进行遍历(JDK 8新方法)

16. HashMap

键值key唯一,value与键值一一对应

存储数据采用的哈希表结构,元素存储无序

自定义类需要重写键的 hashCode() 方法、equals() 方法。

  • 哈希表结构

JDK1.8 之前底层是 数组和链表 ,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。
JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间。

“拉链法” 是指将链表和数组相结合。一个数组的每个位置都可以有一个链表。若遇到哈希冲突定位到同一个数组位置,则将冲突的值加到链表中即可。

  • 构造方法
方法体 解释
HashMap() 构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)
HashMap(int initialCapacity) 构造一个空的 HashMap 具有指定的初始容量和默认负载因子(0.75)
HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap 具有指定的初始容量和负载因子
HashMap(Map<? extends K,? extends V> m) 构造一个新的 HashMap 与指定的相同的映射 Map
  • 使用示例
import java.util.HashMap;

public class HashMapDemo {
    
    
    public static void main(String[] args) {
    
    
        HashMap<String, String> map = new HashMap<>();
        map.put("紫色", "夜刀神十香");
        map.put("红色", "时崎狂三");
        map.put("白色", "鸢一折纸");
        map.put("粉色", "诱宵美九");
        map.put("绿色", "四糸乃");
        System.out.println(map);        //{粉色=诱宵美九, 紫色=夜刀神十香, 白色=鸢一折纸, 绿色=四糸乃, 红色=时崎狂三}

        System.out.println("键值对个数:" + map.size());  //键值对个数:5

        System.out.println(map.get("白色"));      //鸢一折纸

        System.out.println(map.containsKey("粉色"));      //true

        System.out.println(map.containsValue("夜刀神十香"));     //true

        System.out.println(map.remove("绿色"));       //四糸乃

        System.out.println(map.remove("粉色", "诱宵美九"));   //true

        System.out.println(map);    //{紫色=夜刀神十香, 白色=鸢一折纸, 红色=时崎狂三}

        System.out.println(map.replace("白色", "崇宫澪"));   //鸢一折纸

        map.clear();
        System.out.println(map);    //{}
    }
}

17. LinkedHashMap

  • 继承 HashMap,存储数据采用的哈希表结构+链表结构

  • 使用双向链表来维护内部元素的关系,可以保证存取顺序

  • 通过哈希表结构可以保证的键的唯一、不重复

  • 自定义类需要重写键的 hashCode() 方法、equals() 方法

  • 代码示例
import java.util.LinkedHashMap;

public class LinkedHashMapDemo {
    
    
	public static void main(String[] args) {
    
    
		LinkedHashMap<String, String> lhm = new LinkedHashMap<String, String>();
		lhm.put("纯白", "鸢一折纸");
		lhm.put("夜黑", "本条二亚");
		lhm.put("黑红", "时崎狂三");
		lhm.put("青绿", "四糸乃");
		lhm.put("焰红", "五河琴里");
		lhm.put("紫金", "星空六喰");
		lhm.put("碧绿", "七罪");
		lhm.put("炫橙", "八舞耶俱矢&八舞夕弦");
		lhm.put("粉红", "诱宵美九");
		lhm.put("暗紫", "夜刀神十香");
		System.out.println(lhm);
	}
}

18. TeeMap

  • 键值key唯一,会自动给元素排序,用 key 值默认按字典序排序
  • 可以自定义排序:自然排序和定制排序
  • 有许多特有方法,可以用来操作集合
  • 代码示例
public class TreeMapDemo {
    
    
    public static void main(String[] args) {
    
    
        TreeMap<Integer, String> tree = new TreeMap<>();
        tree.put(1, "aaa");
        tree.put(4, "fff");
        tree.put(6, "ddd");
        tree.put(2, "ccc");
        tree.put(5, "aaa");
        tree.put(3, "bbb");
        System.out.println(tree);
    }
}
//输出
{
    
    1=aaa, 2=ccc, 3=bbb, 4=fff, 5=aaa, 6=ddd}
  • 实现自然排序和定制排序可以参考TreeSet的自定义排序

19. Hashtable

结构和hashMap类似,也是散列表,而Hashtable继承Dictionary,HashMap继承AbstractMap。

用法差不多,讲一下他们的区别吧。

  • Null 值的支持

Hashtable:key和value都不能为null。

HashMap:key可以为null,但是这样的key只能有一个,因为必须保证key的唯一性;可以有多个key值对应的value为null。

  • 安全性不同

Hashtable是线程安全的,它的每个方法上都有synchronized 关键字,因此可直接用于多线程中。

HashMap是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,因此需要开发人员自己处理多线程的安全问题。

虽然HashMap是线程不安全的,但是它的效率远远高于Hashtable。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap也是线程安全,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。所以HashTable 基本被淘汰,很少使用。

  • 初始容量大小和每次扩充容量大小的不同

创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充变为原来的 2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的 2 倍。
创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小。

  • 底层数据结构

HashTable没有将链表转化为红⿊树的机制。


20. Properties集合(属性集)

  • 实现了 Map 接口,继承于 Hashtable
  • IO 相关的方法
  • 经常用于java语言的文件配置,如数据库的配置 jdbc.properties ,系统参数配置 system.properties
  • 表示一个持久的属性集,属性列表中每个键及其对应值都是字符串
  • 构造方法
构造方法 解释
Properties() 创建一个没有默认值的空属性列表。
Properties(Properties propDefault) 创建具有指定默认值的空属性列表。
  • 常用成员方法
成员方法 解释
String getProperty(String key) 通过键获取值
Object setProperty(String key, String value) 向集合中添加数据
void load(InputStream inStream) 从输入字节流中读取文件内容
void load(Reader reader) 以简单的线性格式从输入字符流读取属性列表
void store(OutputStream out, String comments) load(InputStream) 方法加载到 Properties 表中的格式输出流
void store(Writer writer, String comments) load(Reader) 方法的格式输出到输出字符流。
Set stringPropertyNames() 遍历属性集,获取所有键,返回一个 set 集合
  • 代码示例
import java.util.Properties;

public class PropertiesDemo {
    
    
	public static void main(String[] args) {
    
    
		Properties prop = new Properties();
		
		//向集合中添加数据
		prop.setProperty("username", "admin");
		prop.setProperty("password", "123456");
		
		//获取集合数据
		String a = prop.getProperty("username");
		String b = prop.getProperty("password");
		
		System.out.println(a + "==" + b);
	}
}

21. 四种Map遍历方式(Iterator迭代器)

// 作为主函数调用
public class MapForOut {
    
    
    public static void main(String[] args) {
    
    
        HashMap<String, String> map = new HashMap<>();
        map.put("纯白", "鸢一折纸");
        map.put("夜黑", "本条二亚");
        map.put("黑红", "时崎狂三");
        map.put("青绿", "四糸乃");
        map.put("焰红", "五河琴里");
        map.put("紫金", "星空六喰");
        map.put("碧绿", "七罪");
        map.put("炫橙", "八舞耶俱矢&八舞夕弦");
        map.put("粉红", "诱宵美九");
        map.put("暗紫", "夜刀神十香");
        System.out.println(map);
        //调用方法
        //XXXX(map)
    }
}
  • keySet()方法

先将 Map 集合中所有键对象转换为 Set 单列集合,接着将包含键对象的 Set 集合

转换为 Iterator 接口对象,然后遍历 Map 集合中所有的键,再根据键获取相应的值

public static void threadKeySet(HashMap<String, String> map) {
    
    
    Set<String> keys = map.keySet();
    //1、迭代器Iterator()输出
    Iterator<String> it = keys.iterator();
    while (it.hasNext()) {
    
    
        Object key = it.next();
        Object vaule = map.get(key);
        System.out.println(key + ":" + vaule);
    }
    
    System.out.println("-----------------------");

    //2、增强for输出
    for (String key : keys) {
    
    
        String vaule = map.get(key);
        System.out.println(key + ":" + vaule);
    }
}
  • entrySet()法

将原有 Map 集合中的键值对作为一个整体返回为 Set 集合,接着将包含键值对对象的 Set 集合

转换为 Iterator 接口对象,然后获取集合中的所有的键值对映射关系,再从映射关系中取出键和值。

public static void threadEntryKey(HashMap<String, String> map) {
    
    
    Set<Map.Entry<String, String>> entrys = map.entrySet();
    //1、迭代器Iterator()输出
    Iterator<Map.Entry<String, String>> it = entrys.iterator();
    while (it.hasNext()) {
    
    
        Object keyValue = it.next();
        System.out.println(keyValue);
    }

    System.out.println("-----------------------");

    //2、增强for输出
    for (Entry<String, String> entry : entrys) {
    
    
        System.out.println(entry);
    }
}
  • forEach()+Lambda表达式
public static void threadForEach(HashMap<String, String> map) {
    
    
    map.forEach((String key, String value) -> System.out.println(key + "=" + value));
}
  • values()方法

说明:在 Map 集合中,除了以上介绍的主要的遍历方式外,还提供了一个 values() 方法,通过这个方法可以直接获取 Map 中存储所有值的 Collection 集合。

public static void threadValues(HashMap<String, String> map) {
    
    
    Collection<String> values = map.values();
    values.forEach((String value) -> System.out.println(value));
}

22. 随笔

在这里插入图片描述

Guess you like

Origin blog.csdn.net/m0_48489737/article/details/127680287