写在前面
你们好,我是小庄。很高兴能和你们一起学习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 个索引元素,i 从0 开始 |
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文件读写操作