Java集合详解之Arraylist的使用

今天开始,围绕集合的问题将进行一周时间的学习和练习以熟练掌握Java中集合的应用,先围绕集合概述Collection,然后对Arraylist进行学习分析介绍,并且加入大量代码练习
1.1.什么是集合
存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,存储对象,集合是存储对象最常用的一种方式。
集合的出现就是为了持有对象。集合中可以存储任意类型的对象, 而且长度可变。在程序中有可能无法预先知道需要多少个对象, 那么用数组来装对象的话, 长度不好定义, 而集合解决了这样的问题。
1.2.集合和数组的区别
数组和集合类都是容器
数组长度是固定的,集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象数组中存储数据类型是单一的,集合中可以存储任意类型的对象。
集合类的特点
用于存储对象,长度是可变的,可以存储不同类型的对象。

1.2.1.数组的缺点
存储类型单一的数据容器,操作复杂(数组一旦声明好不可变)CRUD

1.3.集合的分类
集合做什么
1:将对象添加到集合
2:从集合中删除对象
3: 从集合中查找一个对象
4:从集合中修改一个对象就是增删改查
注意:集合和数组中存放的都是对象的引用而非对象本身
Java工程师对不同的容器进行了定义,虽然容器不同,但是还是有一些共性可以抽取最后抽取了一个顶层接口,那么就形成了一个集合框架。如何学习呢?当然是从顶层学起,顶层里边具有最共性,最基本的行为。具体的使用,就要选择具体的容器了。为什么? 因为不断向上抽取的东西有可能是不能创建对象的.抽象的可能性很大,并且子类对象的方法更多一些. 所以是看顶层,创建底层。那么集合的顶层是什么呢 叫做Collection
集合框架体系

—|Collection: 单列集合
—|List: 有存储顺序, 可重复
—|ArrayList: 数组实现, 查找快, 增删慢
由于是数组实现, 在增和删的时候会牵扯到数组
增容, 以及拷贝元素. 所以慢。数组是可以直接
按索引查找, 所以查找时较快
—|LinkedList: 链表实现, 增删快, 查找慢
由于链表实现, 增加时只要让前一个元素记住自
己就可以, 删除时让前一个元素记住后一个元
素, 后一个元素记住前一个元素. 这样的增删效
率较高但查询时需要一个一个的遍历, 所以效率
较低
—|Vector: 和ArrayList原理相同, 但线程安全, 效率略低
和ArrayList实现方式相同, 但考虑了线程安全问
题, 所以效率略低
—|Set: 无存储顺序, 不可重复
—|HashSet
—|TreeSet
—|LinkedHashSet
—| Map: 键值对
—|HashMap
—|TreeMap
—|HashTable
—|LinkedHashMap

为什么出现这么多集合容器,因为每一个容器对数据的存储方式不同,这种存储方式称之为数据结构(data structure)
注意 集合和数组中存放的都是对象的引用。

1.4.什么时候该使用什么样的集合
Collection 我们需要保存若干个对象的时候使用集合。

List

如果我们需要保留存储顺序, 并且保留重复元素, 使用List.

如果查询较多, 那么使用ArrayList
如果存取较多, 那么使用LinkedList
如果需要线程安全, 那么使用Vector

Set
如果我们不需要保留存储顺序, 并且需要去掉重复元素, 使用Set.
如果我们需要将元素排序, 那么使用TreeSet
如果我们不需要排序, 使用HashSet, HashSet比
TreeSet效率高.
如果我们需要保留存储顺序, 又要过滤重复元素, 那么使用LinkedHashSet

2.集合类(Collection)
Collection接口有两个子接口:
List(链表|线性表)
Set(集)
特点:
Collection中描述的是集合共有的功能(CRUD)
List可存放重复元素,元素存取是有序的
Set不可以存放重复元素,元素存取是无序的
java.util.Collection
—| Collection 描述所有接口的共性
----| List接口 可以有重复元素的集合
----| Set 接口 不可以有重复元素的集合

2:学习集合对象
学习Collection中的共性方法,多个容器在不断向上抽取就出现了该体系。发现Collection接口中具有所有容器都具备的共性方法。查阅API时,就可以直接看该接口中的方法。并创建其子类对象对集合进行基本应用。当要使用集合对象中特有的方法,在查看子类具体内容。
查看api 文档Collection在在java.util 中(注意是大写Collection)
注意在现阶段遇到的 E T 之类的类型,需要暂时理解为object 因为涉及到了泛型.
3:创建集合对象,使用Collection中的List的具体实现类ArrayList
1:Collection coll=new Arraylist();
2.1.Collection接口的共性方法
增加:
1:add() 将指定对象存储到容器中
add 方法的参数类型是Object 便于接收任意对象
2:addAll() 将指定集合中的元素添加到调用该方法和集合中
删除:
3:remove() 将指定的对象从集合中删除
4:removeAll() 将指定集合中的元素删除
修改
5:clear() 清空集合中的所有元素
判断
6:isEmpty() 判断集合是否为空
7:contains() 判断集合何中是否包含指定对象

	8:containsAll() 判断集合中是否包含指定集合
                        使用equals()判断两个对象是否相等  

获取: 9:int size() 返回集合容器的大小

转成数组10: toArray() 集合转换数组
2.1.1.增加:
public static void main(String[] args) {
Collection list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
System.out.println(list);
// [计算机网络, 现代操作系统, java编程思想]

	// 增加2 将list容器元素添加到list2容器中
	Collection list2 = new ArrayList();
	list2.add("java核心技术");
	list2.addAll(list);
	list2.add("java语言程序设计");
	System.out.println(list2);
	// [java核心技术, 计算机网络, 现代操作系统, java编程思想, java语言程序设计]
}

2.1.2.删除:
// 删除1 remove
boolean remove = list2.remove(“java核心技术”);
System.out.println(remove); // true
System.out.println(list2); //
//删除2 removeAll() 将list中的元素删除
boolean removeAll = list2.removeAll(list);
System.out.println(removeAll);//true
System.out.println(list2);//[java语言程序设计]
2.1.3.修改:
public static void main(String[] args) {
Collection list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// 修改 clear() 清空集合中的所有元素
list.clear();
System.out.println(list); //[]
}

2.1.4.判断:
public static void main(String[] args) {
Collection list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);

	boolean empty = list.isEmpty();
	System.out.println(empty);// false
	boolean contains = list.contains("java编程思想");
	System.out.println(contains);// true
	Collection list2 = new ArrayList();
	list2.add("水许传");
	boolean containsAll = list.containsAll(list2);
	System.out.println(containsAll);// false

}

2.1.5.获取:
public static void main(String[] args) {
Collection list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// 获取 集合容器的大小
int size = list.size();
System.out.println(size);
}

2.1.6.练习:集合中添加自定义对象
该案例要求完成使用集合:
public static void main(String[] args) {

	// 创建集合对象
	Collection coll = new ArrayList();

	// 创建Person对象
	Person p1 = new Person("jack", 25);
	Person p2 = new Person("rose", 22);
	Person p3 = new Person("lucy", 20);
	Person p4 = new Person("jack", 25);

	// 集合中添加一些Perosn

	// 删除指定Person

	// 删除所有Person

	// 判断容器中是否还有Person

	// 判断容器中是否包含指定Person

	// 获取容器中Person的个数

	// 将容器变为数组,遍历除所有Person

}

分析:
1:Person类
1:姓名和年龄
2:重写hashCode和equals方法
1:如果不重写,调用Object类的equals方法,判断内存地址,为false
1:如果是Person类对象,并且姓名和年龄相同就返回true
2:如果不重写,调用父类hashCode方法
1:如果equals方法相同,那么hashCode也要相同,需要重写hashCode方法
3:重写toString方法
1:不重写,直接调用Object类的toString方法,打印该对象的内存地址
Person类
class Person {
private String name;
private int age;

public Person() {

}

public Person(String name, int age) {

	this.name = name;
	this.age = age;
}

@Override
public int hashCode() {
	return this.name.hashCode() + age;
}

@Override
public boolean equals(Object obj) {
	if (!(obj instanceof Person)) {
		return false;
	}
	Person p = (Person) obj;
	return this.name.equals(p.name) && this.age == p.age;
}

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

}

public static void main(String[] args) {
Person p1 = new Person(“张三”, 19);
Person p2 = new Person(“李四”, 20);
Person p3 = new Person(“王五”, 18);
Collection list = new ArrayList();
list.add(p1);
list.add(p2);
list.add(p3);
// isEmpty() 判断集合是否为空
boolean empty = list.isEmpty();
System.out.println(empty);
// 返回集合容器的大小
int size = list.size();
System.out.println(size);
// contains()判断集合何中是否包含指定对象
boolean contains = list.contains(p1);
System.out.println(contains);

	// remove(); 将指定的对象从集合中删除
	list.remove(p1);
	
	// clear() 清空集合中的所有元素
	list.clear();
	System.out.println(list);

}

//使用集合存储自定义对象2
class Book {
private String name;
private double price;

public Book() {

}

public Book(String name, double price) {
	this.name = name;
	this.price = price;
}

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public double getPrice() {
	return price;
}

public void setPrice(double price) {
	this.price = price;
}

@Override
public int hashCode() {
	return (int) (this.name.hashCode() + price);
}

@Override
public boolean equals(Object obj) {
	if (!(obj instanceof Book)) {
		return false;
	}
	Book book = (Book) obj;
	return this.name.equals(book.name) && this.price == book.price;
}

@Override
public String toString() {
	return "book:@ name:" + this.name + ", price:" + this.price;
}

}
public class Demo1 {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book(“think in java”, 100));
col.add(new Book(“core java”, 200)); System.out.println(col);
}
}

2.2.List
—| Iterable 接口
Iterator iterator()
----| Collection 接口
------| List 接口 元素可以重复,允许在指定位置插入元素,并通过索
引来访问元素
2.2.1.List集合特有方法
1:增加
void add(int index, E element) 指定位置添加元素
boolean addAll(int index, Collection c) 指定位置添加集合
2:删除
E remove(int index) 删除指定位置元素

3:修改
E set(int index, E element) 返回的是需要替换的集合中的元素
4:查找:
E get(int index) 注意: IndexOutOfBoundsException
int indexOf(Object o) // 找不到返回-1
lastIndexOf(Object o)
5:求子集合
List subList(int fromIndex, int toIndex) // 不包含toIndex

2.2.1.1.增加
public static void main(String[] args) {
List list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// add,在0角标位置添加一本书
list.add(0, “舒克和贝塔”);
System.out.println(list);
// 在list2集合的1角标位置添加list集合元素
List list2 = new ArrayList();
list2.add(“史记”);
list2.add(“资治通鉴”);
list2.add(“全球通史”);
boolean addAll = list2.addAll(1, list);
System.out.println(addAll); //true System.out.println(list2);
}
2.2.1.2.删除
public static void main(String[] args) {
List list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// 删除0角标元素
Object remove = list.remove(0);
System.out.println(remove);
}
2.2.1.3.修改:
public static void main(String[] args) {
List list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// 修改2角标位置的书,返回的原来2角标位置的书
Object set = list.set(2, “边城”);
System.out.println(set); //java编程思想
System.out.println(list);

}

查找
List list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
System.out.println(list);
// 查找: E get(int index) 注意角标越界
Object set = list.get(list.size() - 1);
System.out.println(set); // java语言程序设计
System.out.println(list);
list.get(list.size()); //IndexOutOfBoundsException
}

2.2.1.4.查找
public static void main(String[] args) {
List list = new ArrayList();
// 增加:add() 将指定对象存储到容器中
list.add(“计算机网络”);
list.add(“现代操作系统”);
list.add(“java编程思想”);
list.add(“java核心技术”);
list.add(“java语言程序设计”);
list.add(“java编程思想”);
System.out.println(list);
// 查找: E get(int index) 注意角标越界
Object set = list.get(list.size() - 1);
System.out.println(set); // java语言程序设计
System.out.println(list);
// list.get(list.size()); //IndexOutOfBoundsException

	// indexOf(Object o) 返回第一次出现的指定元素的角标
	int indexOf = list.indexOf("java编程思想");
	System.out.println(indexOf); // 2
	// 没有找到,返回-1
	int indexOf2 = list.indexOf("三国志");
	System.out.println(indexOf2); // -1

	// lastIndexOf 返回最后出现的指定元素的角标
	int lastIndexOf = list.lastIndexOf("java编程思想");
	System.out.println(lastIndexOf); // 5
}

2.2.2.ArrayList
–| Iterable
----| Collection
------| List
---------| ArrayList 底层采用数组实现,默认10。每次增长
60%,((oldCapacity * 3)/2 + 1) 查询快,增删慢。
---------| LinkedList
ArrayList:实现原理:
数组实现, 查找快, 增删慢
数组为什么是查询快?因为数组的内存空间地址是连续的.
ArrayList底层维护了一个Object[] 用于存储对象,默认数组的长度是10。可以通过 new ArrayList(20)显式的指定用于存储对象的数组的长度。
当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来的容量的1.5倍。
由于ArrayList是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快
可以考虑,假设向数组的0角标未知添加元素,那么原来的角标位置的元素需要整体往后移,并且数组可能还要增容,一旦增容,就需要要将老数组的内容拷贝到新数组中.所以数组的增删的效率是很低的.

练习:去除ArrayList集合中重复元素
1:存入字符串元素
2:存入自定义对象元素(如Perosn对象)
原理:
循环遍历该集合,每取出一个放置在新的集合中,放置之前先判断新的集合是否以包含了新的元素。
思路:
存入人的对象.
1先定义person 类
2将该类的实例存入集合
3 将对象元素进行操作. 注意:自定义对象要进行复写toString 和 equals 方法.
为什么? 因为object 是person 的父类,object 中的toString 返回的是哈希值,object 类中equals
方法比较的是对象的地址值.
思路
1存入字符串对象
2存入自定义对象 如person
2创建容器,用于存储非重复元素
3对原容器进行遍历,在遍历过程中进行判断遍历到的元素是否在容器中存在.(contains)
4如果存在,就不存入,否则存入.
5 返回新容器

public class Demo6 {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
Person p1 = new Person(“jack”, 20);
Person p2 = new Person(“rose”, 18);
Person p3 = new Person(“rose”, 18);
arr.add(p1);
arr.add(p2);
arr.add(p3);
System.out.println(arr);
ArrayList arr2 = new ArrayList();
for (int i = 0; i < arr.size(); i++) {
Object obj = arr.get(i);
Person p = (Person) obj;
if (!(arr2.contains§)) {
arr2.add§;
}
}
System.out.println(arr2);
}
}

class 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 hashCode() {
	return this.name.hashCode() + age * 37;
}

@Override
public boolean equals(Object obj) {
	if (!(obj instanceof Person)) {
		return false;
	}
	Person p = (Person) obj;

	return this.name.equals(p.name) && this.age == p.age;
}

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

}

在实际的开发中ArrayList是使用频率最高的一个集合。
今天就学习到Arraylist集合,下一节开始了解Linkedlist集合

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值