数据类型

数据类型分为基本类型(值类型)和引用类型(类似于指针)。==基本类型默认初始化值为0,引用类型默认初始化值为null==。

基本类型

数值类型:byte(8bit)、short(16bit)、intlongfloat(32bit)、double(64bit)、boolean

字符类型:char(16bit Unicode)。

基本类型作为类成员,

字面值

前缀0表示八进制,而前缀0x代表十六进制。

字符串字面值(常量)包含在双引号间:“Hello World”

字符常量和字符串常量可以包含转义字符以及Unicode字符编号:‘\u0001’

类型转换

进行运算时,低精度自动向高精度转换(例如shortintfloatdouble),使用强制转换从高精度向低精度转换(可能损失数据)。

long y = 1234;
int x = (int) y;  //强制类型转换

包装类

当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类,例如:Integer, Long, Char等。

数值类型包装类基于Number类,提供常用的静态方法:

计算值

返回字符串所表示的对应类型的字面值。

static Type valueOf(String s[, int radix])
static int parseInt(String s[, int radix])
数值转换为文本
static String toString(int i)		// for all basic types

字符类型对应的包装类为Character

字符串

由于字符串是常用的一类数据类型,因此将String也归为基本类型,默认值为nullString 类是不可改变的,对字符串的修改方法都会返回新的字符串对象。如果需要对字符串做修改,应该选择使用 StringBuffer & StringBuilder 类

str = "This is a string";
str = new String(byte[] buffer,int offset, int length);

格式化字符串

String format("%d %f %s", args);
String valueOf(Type x); // == toString

查找和索引

char charAt(int index);
int indexOf(int ch[, int fromIndex]);
int indexOf(String str[, int fromIndex]);
int lastIndexOf(int ch[, int fromIndex]);
int lastIndexOf(String str[, int fromIndex]);
boolean startWith(String prefix);
boolean endsWith(String suffix);
boolean matches(String regex);
String substring(int beginIndex[, int endIndex]);

修改

替换:

String replace(char oldChar, char newChar);  // replace all
String replaceAll(String regex, String replacement);
String replaceFirst(String regex, String replacement);

根据正则表达式拆分字符串,注意转义字符。

String[] split(String regex[, int limit])

使用正则表达式支持更加灵活地分割:" ?, ?"" ?= ?"" ?: ?"

字符串拼接:

String concat(String str)
String String.join(delimiters, Iterable);  // since 1.8

使用+操作符等效。

修剪

String trim();	// remove blank space

StringBuffer/StringBuilder

StringBuilder 相较于 StringBuffer 有速度优势,但是StringBuilder的方法不是线程安全的(不能同步访问)。

正则表达式

检测是否匹配模式:

import java.util.regex.Pattern
String text = "this is a string";
String pattern = ".*\\w{4}.*";
boolean matches = Pattern.matches(regex, text);

String.matches也可以执行匹配任务。

返回匹配内容:

Pattern regex = Pattern.compile(pattern);  
Matches matches = regex.match(text);
while(matches.find()){
  println(matches.group(0))
}
n = matches.groupCount();  // 捕获组数量(不包括匹配)
String sub = matches.group(i);  //返回捕获内容

Java字符串会解释转义字符“\”,因此当正则表达式中包含“\”时,需要使用“\\”。

match方法尝试匹配整个字符串,而find方法尝试匹配子串。find一次仅匹配一个字串,并记录匹配位置,可重复在同一Matches对象上调用find以返回后续匹配字串。

替换匹配内容:replaceAllreplaceFirst(等效于String.replaceAllString.replaceFirst)。

Regular Expression in Java - Java Regex Example - JournalDev

容器框架

容器在java.util包中提供,java.util.concurrent提供线程安全容器类型。

数组

一维数组

数组是包装对象,封装了连续的同类型变量。对于基本类型,数据储存于连续的内存空间中;对于对象,则连续存储的为对象的引用,而实际对象储存于堆分段

array

声明数组(的引用):

type[] array_name;	// preferred java ctyle
type array_name[];	// c/c++ style

数组在声明之后,具有默认值(null),必须经过初始化才能使用(可以和声明结合)。

静态初始化

在声明数组时,使用“{...}”为数组的整体赋值,必须紧接在声明之后。

type array_name[] = {value1,value2,...,valuen};
动态初始化

使用new创建具有指定长度的数组。动态初始化不用和声明语句写在一起,也可以将新创建的数组赋值给已定义的数组引用。

array_name = new type[array_size];
访问数组元素
x = array_name[index];

通过下标访问数组元素,下标起始值为0,数组长度可通过字段array_name.length获得。提供的索引不应超过数组长度,否则引起ArrayIndexOutOfBoundsException 异常。

多维数组

多维数组又称为数组的数组,即数组元素储存了另一个数组的引用。

int[][] intArray = new int[10][20]; 		//a 2D array or matrix
int[][][] intArray = new int[10][20][10]; 	//a 3D array
锯齿数组

根据多维数组的定义,我们其实可以先声明数组的最高维,然后为最高维的每一个元素初始化一个子数组。由于子数组长度可能不一样,因此称这样的数组为**锯齿数组**。

int[][] array_name = new int[len1][];
for(int i = 0; i < len1; ++i){
    array_name[i] = new int[len_i];
}

由于多维数组的构造方式,其底层数据的内存空间将不再是连续的。

Arrays类

提供静态方法操作数组,包括排序、比较、查找、赋值等操作。

提供数组与容器类型转换的接口。

容器接口

容器框架是一个用来代表和操纵集合的统一架构,包含如下内容:

  • 接口:是代表集合的抽象数据类型。例如CollectionListSetMap等。之所以定义多个接口,是为了以不同的方式操作集合对象。
  • 实现(类):是集合接口的具体实现,例如:ArrayListLinkedListHashSetHashMap
  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。相同的方法可以在相似的接口上有着不同的实现。

Java 容器框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合;另一种是图(Map),存储键/值对映射。

img

Collection接口存储一组不唯一,无序的对象。

  • List接口存储一组不唯一,有序(插入顺序)的对象。
  • Set接口存储一组唯一,无序的对象。
    • SortedSet接口有序的集合
  • Queue:在容器首端取出元素。通常实现包括FIFO队列(在容器末端插入元素)与优先队列(PriorityQueue,插入位置与元素大小相关)。
  • Dequeue(double-ended queue):支持在容器的两端插入和删除元素。

Map接口存储一组键值对象(字典)。

abstract interface Map<KeyType,ValueType>
  • SortedMap接口使Key保持在升序排列。

容器包装

同步容器

每类容器提供了静态包装方法,返回线程安全的容器类型。

public static  Collection synchronizedCollection(Collection c);
不可修改

检查所有容器操作,如有修改容器的操作则抛出异常。

public static  Collection unmodifiableCollection(Collection<? extends T> c);

容器类型

Note that all the core collection interfaces are generic.

image-20210804123413178

容器类型公共方法

collection.size();
collection.clear();

List

可变长度数组

  • ArrayList在内部维护常规数组;如果数组容量不足,则需要重新分配数组;适用于频繁随机访问元素。
  • LinkedList在内部维护链表;适用于频繁增删元素。
ArrayList<Integer> list = new ArrayList<Integer>();
// new ArrayList<Type>(Collection c);
// new ArrayList<Type>(int capacity);
list.add(element);
list.set(0, 100);      // => list.get(0);  // 不能使用[]运算符
list.remove(0);        // => list.clear(); 
list.sort((x,y)->x-y)  // => Collections.sort(list); 
n = list.size();
tf = list.contains(object);

元素类型必须是引用类型,基本类型需要用包装类代替。

LinkedList提供额外方法(比普通方法更加高效):addFirst/addLastremoveFirst/removeLastgetFirst/getLast

序列和数组相互转换
Integer[] intArray = list.toArray(new Integer[5]);  // cast to array
ArrayList<Integer> list = new Arrays.asList({2,3,0,-1});

Set

操作方法类似于ArrayList。由于元素是无序存储的,没有基于索引的方法。

HashSet and LinkedHashSet

HashSet为无序集合(backed by HashMap,迭代顺序是随机的);

LinkedHashSet通过双向链表维持元素的插入顺序。

TreeSet(SortedSet)

A NavigableSet implementation based on a TreeMap. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time.

Map

存储key-value映射(即字典)。

HashMap
public class HashMap<K,V> extends java.util.AbstractMap 
   implements Map, Cloneable, Serializable;
TreeMap(SortedMap)

A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time.

用法
import java.util.HashMap;
HashMap<String,Object> map = new HashMap<>();
map.put(key ,value);   // => value = map.get(key)
map.remove(key);       // => map.clear()
tf = map.containsKey(key);
tf = map.containsValue(value);
for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
}
for (String key : map.keySet()) {...}
for (Object value : map.values()) {...}

https://stackoverflow.com/a/1066607

https://stackoverflow.com/questions/46898/how-do-i-efficiently-iterate-over-each-entry-in-a-java-map

Queue

PriorityQueue is an unbounded queue based on a priority heap.

旧式数据结构

枚举

可以枚举(一次获得一个)对象集合中的元素。这种传统接口已被迭代器取代,虽然Enumeration 还未被遗弃,但在现代代码中已经被很少使用了。尽管如此,它还是使用在诸如VectorProperties这些传统类所定义的方法中。

区别于C/C++等的枚举类型,其元素是通过其他类型(如Vector.elements),无法定义或直接访问其中的枚举元素。

向量

Vector类实现了一个动态数组,和ArrayList很相似,但是两者是不同的:

  • Vector是同步访问的。
  • Vector包含了许多传统的方法,这些方法不属于集合框架。

Vector支持泛型,如果构造时未给出初始化类型,编译器会给出警告。

StackVector的一个子类,它实现了一个标准的后进先出的栈。

注意:Vector/Stack对象无法使用下标运算符[]访问其对象。

位集合

一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加

字典

Dictionary类是一个抽象类,用来存储键/值对,作用和Map类相似。Dictionary类已经过时了。在实际开发中,你可以实现Map接口来获取键/值的存储功能。

哈希表

Hashtable原本是Dictionary的一个具体实现 。

Java 2 重构的Hashtable实现了Map接口,因此,Hashtable现在集成到了集合框架中。它和HashMap类很相似,但是它支持同步。键经过哈希处理,所得到的散列码被用作存储在该表中值的索引

属性

Properties继承于Hashtable,表示了一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。

Properties类被许多Java类使用。例如在获取环境变量时它就作为System.getProperties()方法的返回值。