集合
关于集合的介绍,绝大多数都是记忆性的知识。所以不再详细介绍。
一.集合的由来:
数组长度是固定的,当添加的元素个数超过了数组长度,需要对数组重新定义太过麻烦。JavaAPI为程序员提供了可变长度的数组。
能存储任意数量的元素。长度随元素的增加而增加,随元素的减少而减少。
二.集合和数组区别:
a.数组的长度是固定的,集合的长度是随着元素的数量改变而改变的。
b.数组可以存储基本数据类型,集合不可以。现在有包装类型的出现,可以将基本类型转换成引用类型存储在集合中。
c.对于基本类型,数组会存储值。集合只存储对象的引用,感谢包装类型的出现。
三.数组和集合的应用:
当长度固定时选择数组,当长度不确定时选择集合。
四. 集合的常用方法演示
boolean add(E e)
boolean remove(Object o)
void clear()
boolean contains(Object o)
boolean isEmpty()
int size()
例子:
class Demo01_Collection{
public static void main(String[] args) {
//Collection是接口,所以只能使用其子类实例化
Collection c = new ArrayList();
//为集合增加元素,而且会返回是否已加入集合的boolean值
c.add("危楼高百尺");
boolean b = c.add("手可摘星辰");
System.out.println("\"手可摘星辰\"是否已经加入集合:" + b);
//remove(Object o)可以移除集合中数据,也能返回是否移除成功的boolean值
boolean b1 = c.remove("手可摘星辰");
System.out.println("\"手可摘星辰\"是否已经移除成功:" + b1);
//clear():清空集合
c.clear();
//isEmpty():返回集合元素个数是否为零;
System.out.println("clear()后集合是否为空:" + c.isEmpty());
//size():返回集合元素个数,因为已经清空,所以返回长度为零
System.out.println("clear()后集合长度为:" + c.size());
}
}
执行结果:
"手可摘星辰"是否已经加入集合:true
"手可摘星辰"是否已经移除成功:true
clear()后集合是否为空:true
clear()后集合长度为:0
五.集合的遍历:
- 集合转数组遍历
- 集合中Iterator遍历
例子:
class Demo02_Iterator{
public static void main(String[] args) {
//ArrayList重写了toString方法会调用每个元素的toString方法。
Collection c = new ArrayList();
c.add(new Student("张三", 25));
c.add(new Student("李四", 24));
c.add(new Student("王五", 23));
//使用集合iterator()方法返回Iterator对象遍历
withIterator(c);
//将集合转变为数组进行遍历
withArray(c);
}
//将集合转变为数组进行遍历
public static void withArray(Collection c) {
//将集合转为数组
Object[] arr = c.toArray();
//对集合使用for循环
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
//使用集合iterator()方法返回Iterator对象遍历
public static void withIterator(Collection c) {
//返回Iterator对象
Iterator iterator = c.iterator();
//Iterator对象有一个hasNext()方法用于确定是否还有元素,next()返回下一个元素。所使用while循环
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
}
/*
* 用于验证集合存储元素的遍历
*/
class Student{
private String name;
private int age;
//带参构造方法
public Student(String name, int age){
this.name = name;
this.age = age;
}
//重写toString()方便遍历时显示
@Override
public String toString() {
return "(name = " + name + ", age = " + age + ")";
}
}
执行结果:
(name = 张三, age = 25)
(name = 李四, age = 24)
(name = 王五, age = 23)
(name = 张三, age = 25)
(name = 李四, age = 24)
(name = 王五, age = 23)
六.集合框架带All的功能
boolean addAll(Collection c)
boolean removeAll(Collection c)
boolean containsAll(Collection c)
boolean retainAll(Collection c)
例子:
class Demo03_CollectionAll{
public static void main(String[] args) {
//定义c1对象并添加元素并显示
Collection c1 = new ArrayList();
c1.add("天");
c1.add("地");
System.out.print("c1:");
showCollection(c1);
//定义c2对象并添加元素并显示
Collection c2 = new ArrayList();
c2.add("玄");
c2.add("黄");
System.out.print("c2:");
showCollection(c2);
//addAll(Collection c)可以添加一个集合对象,也可以返回是否添加成功的boolean值
c1.addAll(c2);
System.out.println("为c1添加c2后的遍历:");
showCollection(c1);
//containsAll(Collection c)可以检查在原集合是否存在c
System.out.println("新的c1是否包含有c2:" + c1.containsAll(c2));
//removeAll(Collection c)可以在原集合中移除c中的元素
c1.removeAll(c2);
System.out.print("在c1中移除c2中元素后c1的元素:");
showCollection(c1);
//为c1添加新c2中元素一遍后期retainAll(Collection c)
c1.addAll(c2);
System.out.println("为c1添加c2中元素后c1为:");
showCollection(c1);
//retainAll(Collection c)得到愿集合和c中交集
c1.retainAll(c2);
System.out.println("为c1求出和c2中交集后c2的元素:");
showCollection(c1);
}
//遍历并显示集合中元素。
public static void showCollection(Collection c){
Iterator iter = c.iterator();
while(iter.hasNext()){
System.out.print(iter.next() + "\t");
}
System.out.println();
}
}
执行结果:
c1:天 地
c2:玄 黄
为c1添加c2后的遍历:
天 地 玄 黄
新的c1是否包含有c2:true
在c1中移除c2中元素后c1的元素:天 地
为c1添加c2中元素后c1为:
天 地 玄 黄
为c1求出和c2中交集后c2的元素:
玄 黄
七.List是Collection的子接口。每一个元素有一个对应的下标。所以List比Collection多出了关于下标的方法
void add(int index,E element)
E remove(int index)
E get(int index)
E set(int index,E element)
List常用的实现类有ArrayList和LinkedList
ArrayList是使用数组存储元素。查询快,修改也快。但是增删慢
LinkedList是使用双列表存储元素,查询慢,修改也慢,但是增删快。
Vector必须同步。很影响效率。一般用于面试题。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
List子实现的使用建议:
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList
例子:
/*
* 调用上一个类的:showCollection方法。
*/
class Demo04_List{
public static void main(String[] args) {
List list = new ArrayList();
list.add("甲");
list.add("乙");
System.out.println("list集合中原有元素是:");
Demo03_CollectionAll.showCollection(list);
//使用List特有方法为list在开头添加两个元素
list.add(0, "丙");
list.add(0, "丁");
System.out.println("在list集合的第零个位置添加两个元素后:");
Demo03_CollectionAll.showCollection(list);
//使用List特有方法为list删除第二个元素后
list.remove(1);
System.out.println("为list删除第二个元素后:");
Demo03_CollectionAll.showCollection(list);
//使用List特有方法从list获得第二个元素
Object obj = list.get(1);
System.out.println("从list获得第二个元素:" + obj);
//使用List特有方法在list中设置第二个元素
list.set(1, "戊");
System.out.println("在list中设置第二个元素:");
Demo03_CollectionAll.showCollection(list);
}
}
执行结果:
list集合中原有元素是:
甲 乙
在list集合的第零个位置添加两个元素后:
丁 丙 甲 乙
为list删除第二个元素后:
丁 甲 乙
从list获得第二个元素:甲
在list中设置第二个元素:
丁 戊 乙
八.去除ArrayList中重复的字符串
分析:
- 去除ArrayList的重复字符串,需要另一个定义的ArrayList保存去除过后的ArrayList
- 因为需要比较字符串是否重复,所有需要重写equals方法。API已经重写过。
- 如果ArrayList中加入其他对象,那么该对象所在类需要重写equals方法
例子:
class Demo05_ArrayList{
public static void main(String[] args) {
ArrayList list = new ArrayList();
//省去重复添加字符。将一个字符串分割并且循环添加
String str = "ljdfalfjalfslglsdj";
String[] arr1 = str.split("");
for(String s : arr1){
list.add(s);
}
System.out.println("没有去重的ArrayList:");
System.out.println(list);
//去除list中重复的字符串
list = singleObject(list);
//输出去重以后的ArrayList
System.out.println("去重以后的ArrayList:");
System.out.println(list);
}
/*
* 去除参数中重复的元素
*/
public static ArrayList singleObject(ArrayList list){
//定义一个不存在重复元素的ArrayList
ArrayList result = new ArrayList();
//遍历参数
for(Object obj : list){
//如果新数组中不存在该元素就加入
if(!result.contains(obj)){
result.add(obj);
}
}
return result;
}
}
执行结果:
没有去重的ArrayList:
[l, j, d, f, a, l, f, j, a, l, f, s, l, g, l, s, d, j]
去重以后的ArrayList:
[l, j, d, f, a, s, g]
九.栈:
后进先出
队列:
先进先出
使用LinkedList模拟两种数据结果
例子:
class Demo06_StackAndQueue{
public static void main(String[] args) {
Stack stack = new Stack();
//省去重复添加字符。将一个字符串分割并且循环添加
String str = "ljdfalfjalfslglsdj";
String[] arr1 = str.split("");
for(String s : arr1){
stack.add(s);
}
System.out.println("栈的加入顺序:");
System.out.println(stack.toString());
System.out.println("栈中元素移除的顺序");
while(!stack.isEmpty()){
System.out.print(stack.remove() + ", ");
}
System.out.println("\r\n\r\n栈和队列华丽丽的分割线----------------------------\r\n");
Queue queue = new Queue();
//省去重复添加字符。将一个字符串分割并且循环添加
for(String s : arr1){
queue.add(s);
}
System.out.println("队列的加入顺序:");
System.out.println(queue.toString());
System.out.println("队列中元素移除的顺序");
while(!queue.isEmpty()){
System.out.print(queue.remove() + ", ");
}
}
//在集合中尾部加上元素,当移除时也移除集合中尾部元素
private static class Stack{
private LinkedList list = new LinkedList();
//在队尾加上元素
public void add(Object obj){
list.addLast(obj);
}
//移除并返回队尾元素
public Object remove(){
return list.removeLast();
}
//判断栈中元素是否为空
public boolean isEmpty(){
return list.isEmpty();
}
//重写toString方便输出
@Override
public String toString(){
return list.toString();
}
}
//在集合中尾部加上元素,当移除时也移除集合中开头的元素
private static class Queue{
private LinkedList list = new LinkedList();
//在队尾加上元素
public void add(Object obj){
list.addLast(obj);
}
//移除并返回集合中开头的元素
public Object remove(){
return list.removeLast();
}
//判断队列中元素是否为空
public boolean isEmpty(){
return list.isEmpty();
}
//重写toString方便输出
@Override
public String toString(){
return list.toString();
}
}
}
执行结果:
栈的加入顺序:
[l, j, d, f, a, l, f, j, a, l, f, s, l, g, l, s, d, j]
栈中元素移除的顺序
j, d, s, l, g, l, s, f, l, a, j, f, l, a, f, d, j, l,
栈和队列华丽丽的分割线----------------------------
队列的加入顺序:
[l, j, d, f, a, l, f, j, a, l, f, s, l, g, l, s, d, j]
队列中元素移除的顺序
j, d, s, l, g, l, s, f, l, a, j, f, l, a, f, d, j, l,
十.HashSet集合可以保证存储元素的唯一性,Set接口对Collection接口没有添加新的方法。
HashSet重写了hashCode、equals方法确定集合中元素的唯一性
TreeSet可以确保元素按照元素的实现的Comparable接口对元素自动进行排序
可以使用元素自己实现的Comparable方法也可以使用自己实现Comparator接口的对象。
LinkedHashSet保证了元素添加进去的顺序。
因为Set的实现类与List实现类最大不同只是不包含重复元素,所以不再演示。
十一:Map接口简介:
将键映射到值
一个映射不能包含重复的键
每个键最多只能映射到一个值
Map是集合,不过Map不是Collection子接口。Set的实现也是依靠Map的实现。
十二:Map方法概述:
a:添加功能
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
d:获取功能
Set<Map.Entry<K,V>> entrySet():
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
e:长度功能
int size():返回集合中的键值对的个数
例子:
class Demo07_Map{
public static void main(String[] args) {
Map map = new HashMap();
//集合中不能防止基本类型。Map放置是因为基本类有一个自动包装的功能
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
map.put(4, "d");
map.put(5, "e");
//Map类冲了toString()方法保证Map对象的正确输出
System.out.println("map:\r\n" + map);
System.out.println("map的键值对个数是:" + map.size());
//Map的获取功能
Set entry = map.entrySet();
System.out.println("通过获取Map的EntrySet对象的遍历:");
for(Object obj : entry){
Entry es = (Entry)obj;
System.out.print(es.getKey() + "=" + es.getValue() + ", ");
}
System.out.println();
Set setKey = map.keySet();
System.out.println("遍历map的键集:");
for(Object obj : setKey){
System.out.print(obj + ", ");
}
System.out.println();
Collection values = map.values();
System.out.println("遍历map的值集:");
for(Object obj : values){
System.out.print(obj + ", ");
}
System.out.println();
//Map的判断功能
System.out.println("map是否包含有\"1\"作为键值:" + map.containsKey(1));
System.out.println("map是否包含有\"a\"做为值值:" + map.containsValue("a"));
System.out.println("map是否为空:" + map.isEmpty());
//Map的删除功能
map.remove(1);
map.remove(2);
System.out.println("删除掉第一个,第二个的元素后的map为:");
System.out.println(map);
System.out.println("通过调用clear()方法后的map为:");
map.clear();
System.out.println(map);
}
}
执行结果:
map:
{1=a, 2=b, 3=c, 4=d, 5=e}
map的键值对个数是:5
通过获取Map的EntrySet对象的遍历:
1=a, 2=b, 3=c, 4=d, 5=e,
遍历map的键集:
1, 2, 3, 4, 5,
遍历map的值集:
a, b, c, d, e,
map是否包含有"1"作为键值:true
map是否包含有"a"做为值值:true
map是否为空:false
删除掉第一个,第二个的元素后的map为:
{3=c, 4=d, 5=e}
通过调用clear()方法后的map为:
{}