史上最全讲解: Java中的二维数组与容器
文章目录
二维数组
定义
数组中存放着数组
语法格式
-
声明 数据类型[][] 数组名
-
初始化
动态初始化: 数据类型[][] 数组名 = new 数据类型[一维的长度][二维的长度];
数据类型[][] 数组名 = new 数据类型[一维的长度][];
静态初始化:数据类型[][] 数组名 = new 数据类型[][]{{‘a’,‘b’},{‘c’,‘d’,‘e’},{‘f’}};
数据类型[][] 数组名 = {{‘a’,‘b’},{‘c’,‘d’,‘e’},{‘f’}};
-
遍历 增强for循环 普通for循环
Arrays
- 操作数组的工具类,静态工厂
- 使用方式:Arrays.静态方法名
- copyOf, fill, equals,sort,toString
容器
定义
容器
- 容器: 存储多个数据,可以是不同数据类型,长度不定
- 变量:存储单个数据,数据类型确定
- 数组:存储多个数据,数据类型唯一,且定长
注意: 容器中的元素类型都为引用类型,不能放置原生数据类型(使用装箱即可),使用泛 型保留类型
自定义容器类
package com.shsxt.collection02;
import java.util.Arrays;
/ * 自定义容器类:
* MyContainer 只能存储字符串数据 ,内部使用数组存储,查询效率高,增删效率低
*/
public class App01 {
public static void main(String[] args) {
//一个容器已经存在
MyContainer my=new MyContainer();
//存储数据
my.add("钢铁侠");
my.add("蜘蛛侠");
my.add("奇异博士");
System.out.println(my.size());
System.out.println(my);
//获取
System.out.println(my.get(0));
System.out.println(my.get(1));
System.out.println(my.get(2));
//修改数据(index,数据)
System.out.println(Arrays.toString(my.revise(2,"123")));
//删除数据(index)
System.out.println(Arrays.toString(my.delete(0)));
}
}
//自定义容器类
class MyContainer{
private String[] arr; //真实内部存储数据的结构
private int size; //容器中存储数据的个数 有默认值0
public MyContainer() {
arr=new String[0];
}
public String[] delete(int index) {
// TODO Auto-generated method stub
String[] temp = arr;
arr = new String[size-1];
int j = 0;
for(int i=0;i<size;i++){
arr[j] = temp[i];
if(j==index){
i++;
arr[index] = temp[i];
}
j++;
}
return arr;
}
public String[] revise(int index,String value) {
// TODO Auto-generated method stub
String[] temp = arr;
arr = new String[size];
int j = 0;
for(int i=0;i<size;i++){
arr[j] = temp[i];
if(j==index){
arr[index] = value;
continue;
}
j++;
}
return arr;
}
//根据索引获取内容
public String get(int index) {
if(index<0 || index>=size){
throw new ArrayIndexOutOfBoundsException();
}
return arr[index];
}
/*
* 添加功能
*/
public void add(String value) {
//对原数组进行备份
String[] temp=arr; //原数组
arr=new String[size+1]; //新数组
//数组的拷贝,原数组中的数据需要拷贝到新数组中
//原数组拿到每一个数据,赋值
for(int i=0;i<=size-1;i++){
arr[i]=temp[i];
}
arr[size]=value;
size++;
}
public int size(){
return this.size;
}
@Override
public String toString() {
return "MyContainer [arr=" + Arrays.toString(arr) + ", size=" + size + "]";
}
}
Collection
Collection是容器的顶层接口
Collection 表示一组对象,它是集中,收集的意思,就是把一些数据收集起来,
Collection 接口的两个子接口:Set 中的数据没有顺序,不可重复;List 中的数据有顺序,可重复
泛型 提高可读性,规范数据的类型
格式:
Collection<String> col = new ArrayList<String>();
-
常见方法
boolean
add(E e) 确保此 collection 包含指定的元素(可选操作)。 boolean contains(Object o) 如果此collection包含指定元素则返回true Iterator iterator 返回在此 collection 的元素上进行迭代的迭代器。 boolean equals(Object o) 比较此 collection 与指定对象是否相等。
iterator遍历
使用是迭代器的步骤:
使用迭代器时,分三步走策略:
第一步:获取对象 ;第二步:判断是否存在下一个;第三步:获取元素
package com.shsxt.list03;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class ListDemo01 {
public static void main(String[] args) {
Collection<String> col = new ArrayList<String>();
col.add("这个杀手不太冷");
col.add("泰坦尼克号");
col.add("tom and Jerry");
Iterator it = col.iterator();
while(it.hasNext()){
System.out.println(it.next());;
}
}
}
List
- List接口特点: 有序(索引),可重复
- 新增方法:可以根据索引操作的方法
- 遍历:增强for,普通for,迭代器 iterator
ListIterator
package com.shsxt.list03;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/*
* 定义一个容器,存放你喜欢的外国电影名,如果存在 这个杀手不太冷,就添加一个哈哈哈(必须要存在这个杀手不太冷...)
* 判断的方式有很多中,都去使用一下看看
*/
public class ListDemo02 {
public static void main(String[] args) {
List<String> ls=new ArrayList();
ls.add("钢铁侠");
ls.add("飓风营救");
ls.add("碟中谍");
ls.add("这个杀手不太冷");
ls.add("当幸福来敲门");
System.out.println(ls);
System.out.println(ls.contains("这个杀手不太冷"));
ListIterator<String> it=ls.listIterator();
//测试使用 boolean hasPrevious() previous() 从后往前逆向遍历list容器
while(it.hasNext()){
it.next();
}
while(it.hasPrevious()){
if("这个杀手不太冷".equals(it.previous())){
it.add("哈哈哈");
}
}
System.out.println(ls);
}
}
ArrayList
-
数据结构: 可变数组实现的
-
特点:根据索引进行查询,遍历效率高,增删效率低,涉及到数据的拷贝问题
-
扩容机制:使用copyOf方法进行动态扩容,为原容量的1.5倍
-
新增方法:无新增方法
package com.shsxt.list03;
/*去创建list的实现类对象,简单操作练习
* 定义ArrayList,存储Person类型的数据,
* 判断new Person("张三",18)在容器中第一次出现的索引
*/
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo03 {
public static void main(String[] args) {
List<Person> ls = new ArrayList<Person>();
ls.add(new Person("张三",18));
ls.add(new Person("李四",18));
ls.add(new Person("王五",18));
System.out.println(ls);
Person person = new Person("张三",18);
System.out.println(person);
System.out.println(ls.indexOf(person));;
}
}
class Person {
private String name;
private int 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;
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Vector
与ArrayList非常像,区别: 1)线程安全的,效率较低 2)每次扩容是原容量的2倍
LinkedList
-
数据结构: 双向链表实现
-
特点:做增删效率高,遍历|根据索引查询效率低
-
新增方法:新增了一些操作与链表头尾的方法
Set
-
特点:无序(存放的顺序和内容真实存储的顺序不一致),不可重复的,可以实现去重效果
-
遍历:
for …each
iterator
HashSet
-
底层结构: 哈希表实现(数组+链表+红黑树)
-
特点: 查询效率高,增删效率高,但是无序
-
底层是由HashMap维护的,就是HashMap中的key
-
使用最多的HashSet方法:
HashSet() 默认初始16个大小,加载因子0.75
HashSet( int initialCapacity) 指定容量的容器,当能够确定存储数据的个数,就是用这个构造器
public class SetDemo02 { public static void main(String[] args) { HashSet hash=new HashSet(); hash.add("哈哈"); hash.add("哈哈"); hash.add("哈哈"); hash.add("哈哈"); hash.add("哈哈"); System.out.println(hash); } }
t() 默认初始16个大小,加载因子0.75
HashSet( int initialCapacity) 指定容量的容器,当能够确定存储数据的个数,就是用这个构造器
public class SetDemo02 {
public static void main(String[] args) {
HashSet hash=new HashSet();
hash.add("哈哈");
hash.add("哈哈");
hash.add("哈哈");
hash.add("哈哈");
hash.add("哈哈");
System.out.println(hash);
}
}
处理HashSet存储的 自定义应用数据类型的去重问题,需要重写hashcode和equals方法,这两个的值都会根据成员属性来计算而不是地址值,hash表结构的特点是先调用hashcode如果值相同在调用equals方法
set类型会进行比较,而list不会因为list可以重复.对于基本数据类型和String类型set会比较,但是其他引用数据类型需要自己定义比较规则.Hashset实现comparable接口
package com.shsxt.set01;
import java.util.HashSet;
/*
* 处理HashSet存储的自定义引用数据类型去重问题:
* 需要对这个对象类型中重写hashcode和equals方法,然后这个两个的值都根据对象的成员属性值进行计算,而非地址值
* hash表结构的特点是先调用hashcode,如果值形同的对象才会进一步调用equals方法进行比较内容,如果hashcode值不相同,根本不会比较equals方法的值
*
*/
public class HashSet01 {
public static void main(String[] args) {
HashSet<Person> set=new HashSet();
set.add(new Person("胡歌",35));
set.add(new Person("杨洋",30));
set.add(new Person("彭于晏",35));
set.add(new Person("彭于晏",35));
System.out.println(set);
}
}
package com.shsxt.set01;
//Person类
public class Person implements Comparable<Person> { //泛型T - 可以与此对象进行比较的那些对象的类型
//public class Person {
private String name;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
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 "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写equals方法,比较对象时比较对象的内容,非地址
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
TreeSet
- TreeSet: 无序,不可重复
- 底层结构: 红黑树进行存储
- 特点: 有序(自动从小到达升序排序) 这里的顺序不是元素插入的顺序 而是对于元素进行比较后的排序
- 可以定义比较规则,**排序规则(compare比较大小进行排序),**并且可以使用去重原则
- 1 内部比较器|自然排序: **实现Comparable接口,重写comparaTo方法,**在方法中定义比较规则.,默认的比较规则
- 2外部比较器|指定比较器:**实现一个Comparator接口,重写compare()方法,**方法的内部定义比较规则
内部比较器的例子
Person实现comparable接口重写compareTo方法
package com.shsxt.set01;
import java.util.HashSet;
public class HashSet01 {
public static void main(String[] args) {
HashSet<Person> set=new HashSet();
set.add(new Person("胡歌",35));
set.add(new Person("杨洋",30));
set.add(new Person("彭于晏",35));
set.add(new Person("彭于晏",35));
System.out.println(set);
}
}
Person类实现了Comparable接口进行比较
package com.shsxt.set01;
public class Person implements Comparable<Person> { //泛型T - 可以与此对象进行比较的那些对象的类型
//public class Person {
private String name;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
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 "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写equals方法,比较对象时比较对象的内容,非地址
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
//根据年龄进行比较,年龄相同就是一个对象
@Override
public int compareTo(Person o) {
//return this.age-o.age;
// return this.age-o.age;
return this.getName().compareTo(o.getName());//根据正负值自动进行排序
}
}
外部比较器的例子
package com.shsxt.set01;
//Person类也为上面的Person
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSet02 {
public static void main(String[] args) {
//TreeSet tree = new TreeSet(new Demo());
//Comparator com = (o1, o2)-> ((Person)o1).getAge()-((Person)o1).getAge();
TreeSet tree = new TreeSet((o1, o2)-> ((Person)o1).getAge()-((Person)o2).getAge());//Lambda表达式
tree.add(new Person("吴彦祖",18));
tree.add(new Person("彭于晏",20));
tree.add(new Person("刘德华",22));
System.out.println(tree);
}
}
//下面的类是一个实现类 只是为了单纯实现Comparator接口
//可以上面使用Lambda表达式
class Demo implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
return o2.getAge()-o1.getAge();
}
}