Java集合框架+工具类

写在前面
  你们好,我是小庄。很高兴能和你们一起学习Java。如果您对Java感兴趣的话可关注我的动态.
  写博文是一种习惯,在这过程中能够梳理和巩固知识。

我们开始吧!

一、数组

在Java基础知识篇我们已经简单的了解数组
数组是Java里面最基础的数据结构,数组是一个存放多个数据的容器

1、数组的特点有哪些呢?

  • 数据是同一类型的,比如都是int类型;
  • 数据是线性排序的,可通过索引进行访问数据,如: a[1];
  • 数据的长度(空间)一旦定义,则不能改变

数组分为一维数组多维数组。实际上,多维数组是数组的数组,存储的方式是一行一行存储,线性存储。

2、数组的定义和初始化:

int[] a;//只是声明,并没有初始化,也可以这样声明 int a[];
int[] b=new int[2];//声明数组并初始化一个可以存储2个整数的数组
b[0]=3;b[1]=5;//初始化数组的值
int[] c=new int[]{1,2,3};//声明的同时初始化,长度为3,值为1,2,3

数组的索引是从0开始的,操作数组时要注意数组越界的问题。

int[] a=new int[3];//声明并初始化了数组长度为3的数组
a[0]=1;//给数组第一个元素(索引为0)赋值
a[2]=10;//给数组第三个元素(索引为2)赋值
a[3]=6;//错误,数组越界,数组长度为3,但最后的元素为a[3-1]

3、操作数组

方法作用
length()获取数组长度
a[i]单个获取数组a中的第i个索引元素,i0开始
for each迭代遍历数组
//给数组赋值
//声明并初始化10个长度的整型数组
int[] a=new int[10];
//定义输入
Scanner in=new Scanner(System.in);
//a.length表示获取数组的长度。注意:获取字符串长度使用的是length(),多了()
for(int i=0;i<a.length;i++){//进行遍历数组逐个赋值
    a[i]=in.nextInt();
}
//获取数组中第i位数,数组索引从0开始
int b=a[2];//此时b的值可以获取索引为2的整数

//for each遍历数组方式
for(int element:a){//a表示数组的变量,element表示数组的元素
    System.out.println(element);//对数组的元素逐个输出
}

4、多维数组

这里我们用二维数组进行讲解,理解了二维数组之后多维数组自然理解了。

二维数组和我们上面讲的一维数组的定义有些不一样,二维数组必须在定义的同时设置好存放的空间(长度)

int a[ ][ ]=new int [ i ][ j ]; i表示行数,j表示列数
注意:
int a[ ][ ]=new int[ ][ ]; 这样定义是错误的;必须设置好长度
int a[ ][ ]=new int[ ][3];这样定义也是错误的,行数必须定义
int[ ][ ] b=new int[2][2]{{0,1},{1,2}};这样定义也是错误
int a[ ][ ]=new int[2][ ];这样定义是正确的 ,列数可以不被定义
数组越界问题

5、多维数组的定义和初始化

//定义了一个两行的数组,具体多少列还不清楚
int[][] a = new int[2][];
//定义了一个两行三列的数组
int[][] c = new int[2][3];
//定义的同时初始化,下面是两行三列的二维数组
int[][] b = new int[][]{{1,2}, {2, 3}, {4, 5}};

6、操作多维数组

//定义了一个两行三列的数组
int[][] a = new int[2][3];
//定义输入
Scanner in=new Scanner(System.in);
//通过for嵌套循环进行赋值二维数组,先遍历某一行,然后遍历这一行中的列对应的值
for(int i=0;i<2;i++){//索引从0开始,这里i=0
	for(int j=0;j<3;j++){//索引从0开始,这里j=0
		//给二维数组赋值
		a[i][j]=in.nextInt();
	}
}
//通过for each遍历二维数组
for(int[] i:a){
	for(int j:i){
	  System.out.println(j);
	}
}
//通过for循环遍历二维数组
for(int i=0;i<2;i++){//索引从0开始,这里i=0
	for(int j=0;j<3;j++){//索引从0开始,这里j=0
		//打印结果
		System.out.println(a[i][j]);
	}
}

二、List列表

1、List的介绍:

List的特点

  • 允许重复数据
  • 数据类型一致
  • 有序的,底层实现Collection接口

List的实现

  • ArrayList(非同步,读取速度快,数组方式存储)
  • LinkedList(非同步的,读取速度一般,删除插入速度快,链表方式存储)
  • Vector(同步的,读取速度慢)

2、ArrayList

方法作用
add(E e)将指定的元素追加到此列表的末尾
add(int index, E element)在此列表中的指定位置插入指定的元素
get(int index)返回此列表中指定位置的元素
isEmpty()如果此列表不包含元素,则返回 true
remove(int index)删除该列表中指定位置的元素
remove(Object o)从列表中删除指定元素的第一个出现(如果存在)
clear()从列表中删除所有元素
contains(Object o)如果此列表包含指定的元素,则返回 true
size()返回此列表中的元素数
import java.util.ArrayList;
public class  ArrayListTest{
	public static void main(String[] args){
		//声明ArrayList列表,类型为Integer对象,int的包装类
		ArrayList<Integer> a=new ArrayList<>();
		//往列表添加元素
		a.add(2);
		a.add(0,3);
		//获取列表中的第一个元素
		System.out.println(a.get(0));
		//获取列表元素数
		System.out.println(a.size());
		//判断列表是否为空,此时为false
		System.out.println(a.isEmpty());		
		//判断列表是否包含指定的元素
		System.out.println(a.contains(3));
		//列表的遍历
		for(int i=0;i<a.size();i++){
			System.out.println(a.get(i));
		}
		//删除下标为0的元素
		a.remove(0);
		//清空列表
		a.clear();	
	}
}

3、LinkedList

ArrayList的方法LinkedList同样都有,但是,LinkedList有自己特殊的方法。
因为LinkedList是链表存储的,所以提供了链表相关的方法:

方法作用
pop()头部删除一个元素
push(E e)头部添加一个元素
addFirst(E e)在该列表开头插入指定的元素
addLast(E e)将指定的元素追加到此列表的末尾

其他方法和ArrayList一样操作,我就不重复写了

import java.util.LinkedList;

public class  LinkedListTest{
	public static void main(String[] args){
		//声明LinkedList
		LinkedList<Integer> a=new LinkedList<>();
		a.push(2);
		a.push(3);
		//通过toString()方法查看存储情况
		System.out.println(a.toString());
		a.pop();
		//通过toString()方法查看存储情况
		System.out.println(a.toString());
		//往尾部添加,add()方法一样
		a.addLast(4);
		a.add(5);
		//通过toString()方法查看存储情况
		System.out.println(a.toString());
		//往头部添加
		a.addFirst(1);
		//通过toString()方法查看存储情况
		System.out.println(a.toString());
	}
}

运行结果:

[3, 2]
[2]
[2, 4, 5]
[1, 2, 4, 5]

Vector的用法和ArrayList几乎是一样的,都是数组存储,主要的区别是Vector是同步的,这里就不对Vector讲解了

如果想让ArrayList同步,可这样实现:使用Collections.synchronizedList()方法进行封装

ArrayList<Integer> a=(ArrayList<Integer>) Collections.synchronizedList(new ArrayList>());

小结:
  1、ArrayList不同步的,适合做大量的查询,效率高
  2、LinkedList不同步的,适合做大量的插入删除操作,效率高
  3、Vector同步
  4、想要实现同步,可以用Collections.synchronizedList()方法进行封装

四、Set集合

1、Set的介绍

集合的特点

  • 不允许重复数据
  • 数据类型一致
  • 不同步的,想要同步必须使用Collections.synchronizedList()方法进行封装

Set的实现

  • HashSet 使用散列存储,无序的
  • LinkedHashSet 使用散列存储和树形结构存储的结合,有序的
  • TreeSet 使用树形结构存储,有序的

2、HashSet

不同步,可以容纳null元素

方法作用
add(E e)将指定的元素追加到此列表的末尾
isEmpty()如果此列表不包含元素,则返回 true
clear()从列表中删除所有元素
contains(Object o)如果此列表包含指定的元素,则返回 true
size()返回此列表中的元素数
remove(Object o)如果存在,则从该集合中删除指定的元素
retainAll(Collection<?> c)计算两个集合的交集
import java.util.HashSet;
public class  HashSetTest{
	public static void main(String[] args){
		//声明HashSet
		HashSet<Integer> h=new HashSet<>();
		//往列表添加元素
		h.add(null);
		h.add(2);
		h.add(3);
		h.add(40000);
		h.add(3);//重复,不添加
		h.add(6);	
		//遍历结果
		for(Integer item:h) {
			System.out.println(item);
		}
		System.out.println("----遍历结束-----");
		//获取列表元素数
		System.out.println(h.size());
		//判断列表是否为空,此时为false
		System.out.println(h.isEmpty());		
		//判断列表是否包含指定的元素
		System.out.println(h.contains(3));
		
		//这里定义另一个集合,并添加元素
		HashSet<Integer> h2=new HashSet<>();
		h2.add(1);
		h2.add(3);
		//计算两个集合的交集
		h.retainAll(h2);
		System.out.println("它们的交集是:"+h);
		//删除指定元素
		h.remove(3);
		//清空列表
		h.clear();
	}
}

运行结果:

null
40000
2
3
6
----遍历结束-----
5
false
true
它们的交集是:[3]

LinkedHashSet 继承HashSet,但是有序的,add()方法添加后遍历是有序的。因为LinkedHashSet上面所有的方法都是HashSet继承的,并且没有重写,所以这里不对LinkedHash进行介绍。

3、TreeSet

基于TreeMap实现,不可以容纳null元素。
根据compareTo()方法指定Comparator排序

方法作用
add(E e)将指定的元素追加到此列表的末尾
isEmpty()如果此列表不包含元素,则返回 true
clear()从列表中删除所有元素
contains(Object o)如果此列表包含指定的元素,则返回 true
size()返回此列表中的元素数
remove(Object o)如果存在,则从该集合中删除指定的元素
first()返回此集合中当前的第一个(最低)元素
import java.util.TreeSet;
public class  TreeTest{
	public static void main(String[] args){
		//声明TreeSet
		TreeSet<Integer> t=new TreeSet<>();
		//往列表添加元素
		//t.add(null);错误
		t.add(2);
		t.add(3);
		t.add(40000);
		t.add(3);//重复,不添加
		t.add(6);	
		//遍历结果
		for(Integer item:t) {
			System.out.println(item);
		}
		System.out.println("----遍历结束-----");
		//获取列表元素数
		System.out.println(t.size());
		//判断列表是否为空,此时为false
		System.out.println(t.isEmpty());		
		//判断列表是否包含指定的元素
		System.out.println(t.contains(3));
		//删除指定元素
		t.remove(3);
		//清空列表
		t.clear();
	}
}

运行结果:

2
3
6
40000
----遍历结束-----
4
false
true

从中我们发现:TreeSet遍历是从小到大的,有序的

4、在对象中使用Set

我们知道,Set集合是不重复的,那么,如果我们在一个对象中使用它时该怎么使用呢?

第一、使用HashSet和LinkedSet时,必须在类中重写Object类的equals()hashCode()toString()方法,否则无法判断是否重复
第二、使用TreeSet时,必须实现Comparable接口,即实现compareTo()方法

例一:新建一个Cat.java类,使用HashSet(LinkedSet)存储Cat对象

public class Cat{
	private int size;
	//有参构造
	public Cat(int s) {	
		this.size=s;
	}
	//获取size
	public int getSize() {
		return size;
	}
	//重写Ojbect类的equals方法
	public boolean equals(Object o) {
		System.out.println("equals正在被调用");
		if(0==size-((Cat) o).getSize()) {
			return true;
		}else {
			return false;
		}
	}
	//重写Object类的hashCode方法
	public int hashCode() {
		System.out.println("hashCode正在被调用");
		return size;
	}
	public String toString() {
		System.out.println("toString正在调用");
		return size+"";
	}
}

例二:新建Dog.java类,使用TreeSet存储对象

public class Dog implements Comparable{
	private int size;
	//有参构造
	public Dog(int s) {	
		this.size=s;
	}
	//获取size
	public int getSize() {
		return size;
	}
	@Override
	public int compareTo(Object o) {
		//若对象的值和传进来的值相等,则返回0
		return size-((Dog)o).getSize();
	}
}

最后我们进行测试

import java.util.HashSet;
import java.util.TreeSet;
public class Test{
	public static void main(String[] args){
		//声明HashSet
		HashSet<Cat> hc=new HashSet<>();
		//声明TreeSet
		TreeSet<Dog> td=new TreeSet<>();
		//往列表添加元素
		hc.add(new Cat(1));
		hc.add(new Cat(2));
		hc.add(new Cat(2));
		System.out.println(hc.size());
		System.out.println("----HashSet使用结束----");
		
		td.add(new Dog(1));
		td.add(new Dog(2));
		td.add(new Dog(2));
		System.out.println(td.size());
		System.out.println("----TreeSet使用结束----");
	}
}

五、Map映射

1、Map的介绍

数学中使用的映射关系是定义域和值域,Map就是以键值对方式存储
一个键对应一个值(key:value)
Map的特点

  • 以键值对的方式进行存储

Map的实现

  • HashMap 不同步,速度快,数据量大
  • Hashtable 同步,速度慢,数据量小
  • Properties 同步,文件格式,数据量小

2、HashMap

最多允许一条记录的键为null,并允许null的值。不支持线程同步,访问速度快。

方法作用
put(K key, V value)将指定的值与此映射中的指定键相关联
get(Object key)返回到指定键所映射的值,或 null如果此映射包含该键的映射
replace(K key, V value)只有当目标映射到某个值时,才能替换指定键的条目
clear()从中删除所有的映射。
isEmpty()如果不包含键值映射,则返回 true
size()返回键值映射的数量
keySet()返回包含的键的Set视图
entrySet()返回包含键值对的Set视图
values()返回包含的值的Collection视图
remove(Object key)删除指定键的映射(如果存在)
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class  MathTest{
	public static void main(String[] args){
		//声明HashMap并设置键值对类型均为String字符串型
		HashMap<String,String> map=new HashMap<>();
		//添加键值对
		map.put("name", "张三");
		map.put("height","170cm" );
		//当键相同,后面的值会覆盖前面的
		map.put("height", "180cm");
		//根据键获取值
		String result=map.get("height");
		//打印结果
		System.out.println(result);
		//根据键替换值
		map.replace("name", "李四");
		//查看结果
		System.out.println(map.get("name"));
		//获取键值对个数,map.size()
		System.out.println("元素个数为:"+map.size());
		//判断键值对是否为空,map.isEmpty()
		System.out.println(map.isEmpty());
		//获取所有值
		System.out.println(map.values());
		
		//定义一个key和value,后面用
		String key;
		String value;
		System.out.println("-----使用EntrySet迭代器遍历-----");
		Iterator<Entry<String,String>> et=map.entrySet().iterator();
		while(et.hasNext()) {
			//System.out.println(et.next());输出格式:key=value
			Map.Entry<String, String> ite=et.next();
			key=ite.getKey();
			value=ite.getValue();
			//打印结果
			System.out.println("键:"+key+" 值:"+value);
		}
		System.out.println("-----使用EntrySet迭代器遍历结束-----");
		System.out.println();
		
		System.out.println("-----使用keySet迭代器遍历-----");
		
		Iterator<String> it=map.keySet().iterator();
		while(it.hasNext()) {
			key=it.next();
			value=map.get(key);
			//打印结果
			System.out.println("键:"+key+" 值:"+value);
			
		}
		System.out.println("-----使用keySet迭代器遍历结束-----");
		//根据键进行删除元素
		map.remove("height");
		//获取键值对个数
		System.out.println("元素个数为:"+map.size());
		//清空
		map.clear();
		//获取键值对个数
		System.out.println("元素个数为:"+map.size());
	}
}

打印结果:

180cm
李四
元素个数为:2
false
[李四, 180cm]
-----使用EntrySet迭代器遍历-----
name=李四
height=180cm
-----使用EntrySet迭代器遍历结束-----

-----使用keySet迭代器遍历-----
键:name 值:李四
键:height 值:180cm
-----使用keySet迭代器遍历结束-----
元素个数为:1
元素个数为:0

简单介绍
LinkedHashMap :维持插入顺序的HashMap(遍历顺序和插入顺序保持一致)
TreeHashMap: 自然数的方式排序,比如数字是从小到大排序

这两个Map和HashMap的关系类似于HashSet和LinkedHashSet、HashSet和TreeSet的关系

3、Hashtable

  • 无序的
  • 适合数据量小的数据
  • 同步
  • key和value都不支持null元素
方法作用
put(K key, V value)将指定的值与此映射中的指定键相关联
get(Object key)返回到指定键所映射的值,或 null如果此映射包含该键的映射
replace(K key, V value)只有当目标映射到某个值时,才能替换指定键的条目
clear()从中删除所有的映射。
isEmpty()如果不包含键值映射,则返回 true
size()返回键值映射的数量
keySet()返回包含的键的Set视图
entrySet()返回包含键值对的Set视图
values()返回包含的值的Collection视图
remove(Object key)删除指定键的映射(如果存在)

这里的用法和HashMap一样,代码大部分重复,只需要改定义

Hashtable<String,String> map=new Hashtable<>();

改完之后运行结果:

180cm
李四
元素个数为:2
false
[180cm, 李四]
-----使用EntrySet迭代器遍历-----
键:height 值:180cm
键:name 值:李四
-----使用EntrySet迭代器遍历结束-----

-----使用keySet迭代器遍历-----
键:height 值:180cm
键:name 值:李四
-----使用keySet迭代器遍历结束-----
元素个数为:1
元素个数为:0

从中可以说明Hashtable是无序的

4、Properties

  • 继承Hashtable类
  • 可以将k-v对保存到文件中
  • 适合数据少的配置文件,比如数据库的配置
  • 除了继承Hashtable的方法外,有自己的方法
load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
store(OutputStream out, String comments)将此属性列表(键和元素对)写入此 Properties表中
getProperty(String key)使用此属性列表中指定的键搜索值
setProperty(String key, String value)设置键和值
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Properties;

public class  PropertiesTest{
	public static void main(String[] args) throws IOException{
		//写入Properties操作
		WriteProperties("Test.properties","name","张三");
		WriteProperties("Test.properties","height","180cm");
		System.out.println("---GetAllProperties---");
		//读取Properties全部信息
		GetAllProperties("Test.properties");
		根据key读取value
		String key="name";
		System.out.println();
		System.out.println("---GetValueByKey---");
		String value=GetValueByKey("Test.properties",key);
		System.out.println("根据"+key+"获取的值为:"+value);
	}
	//写入Properties信息
	public static void WriteProperties(String filePath,String pKey,String pValue) throws IOException {
		File file=new File(filePath);
		//文件不存在
		if(!file.exists()) {
			//新建文件
			file.createNewFile();
		}
		Properties p=new Properties();
		OutputStream out=new FileOutputStream(filePath);
		//设置键值对
		p.setProperty(pKey, pValue);
		//将此属性列表(键和元素对)写入此 Properties表中
		p.store(out, pValue);
		//关闭流
		out.close();
	}
	//读取Properties全部信息
	public static void GetAllProperties(String filePath) throws IOException {		
		Properties p=new Properties();
		InputStream in=new BufferedInputStream(new FileInputStream(filePath));
		//加载所有的键值对
		p.load(in);
		//获取配置文件的名字
		Enumeration e=p.propertyNames();
		//迭代遍历
		while(e.hasMoreElements()) {
		//获取键
		String key=	(String)e.nextElement();
		//根据键获取值
		String value=p.getProperty(key);
		System.out.println("key:"+key+" value:"+value);
		}
	}
	//根据key读取value
	public static String GetValueByKey(String filePath,String key){
	InputStream in=null;
		try {
			Properties p=new Properties();
			in=new BufferedInputStream(new FileInputStream(filePath));
			//加载所有的键值对
			p.load(in);
			//根据传进来的key获取值
			String value=p.getProperty(key);
			//返回值
			return value;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}finally{
			try {
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
}

温馨提示:这里涉及到文件读写操作,如不了解,请看下一篇文章
运行结果:

---GetAllProperties---
key:height value:180cm
key:name value:张三

---GetValueByKey---
根据name获取的值为:张三

六、工具类

  • Arrays
  • Collections

不存储数据,但是提供一些方法,提高我们的工作效率

1、Arrays

方法作用
sort()对数组进行排序
binarySearch()使用二分查找
capyOf()批量拷贝
fill()批量赋值
equals()判定两个数组内容是否相同
import java.util.Arrays;
import java.util.Random;

public class  ArraysTest{
	public static void main(String[] args){
		//new一个随机函数
		Random r=new Random();
		//创建一个长度为5的数组
		int[] a=new int[5];
		for(int i=0;i<a.length;i++) {
			//给数组设置随机数
			a[i]=r.nextInt();
		}
		//使用工具类Arrays排序
		Arrays.sort(a);
		//重新给一个数指定一个值,然后查找
		a[3]=666;
		//使用二分查找进行查值
		int result=Arrays.binarySearch(a, 666);
		System.out.println("666的位置是:"+result);
		
		//把数组a的值拷贝给数组b,只拷贝前三个
		int[] b=Arrays.copyOf(a, 3);
		
		//给数组a批量赋值,全部赋值为66
		Arrays.fill(a, 66);
		//从第1个元素到第3个元素进行批量赋值为1 
		Arrays.fill(a,0,3,1);//[0,3)
		for(int item:a) {
			System.out.println(item);
		}
		System.out.println(a.equals(b));
	}
}

运行结果:

666的位置是:3
1
1
1
66
66
false

2、Collections

Collection处理的对象是Collection和它的子类

方法作用
sort()对List进行排序
binarySearch()使用二分查找List中的元素
fill()批量赋值
max()判断List中的最大值
min()判断List中的最小值
import java.util.ArrayList;
import java.util.Collections;

public class  CollectionsTest{
	public static void main(String[] args){
		//定义一个数组列表
		ArrayList<Integer> list=new ArrayList<>();
		//存储数据
		list.add(1);
		list.add(12);
		list.add(3);
		list.add(20);
		//排序
		Collections.sort(list);
		for(int item:list) {
			System.out.println(item);
		}
		//二分查找
		int result=Collections.binarySearch(list, 3);
		//打印结果
		System.out.println("3在列表中的位置为:"+result);
		//获取最大值
		int max=Collections.max(list);
		System.out.println("最大值为:"+max);
		//获取最小值
		int min=Collections.min(list);
		System.out.println("最小值为:"+min);
		//批量操作,全部赋值666
		Collections.fill(list, 666);
		System.out.println("--批量操作后结果--");
		for(int item:list) {
			System.out.println(item);
		}
	}
}

运行结果:

1
3
12
20
1
最大值为:20
最小值为:1
--批量操作后结果--
666
666
666
666

本篇内容结束,谢谢阅读

上一篇Java常用类库

下一篇Java文件读写操作

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值