为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象进行操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合都是容器,有什么区别?
数组虽然也可以存储对象,但长度是固定的,集合长度是可变的,数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象,不能存储基本数据类型的值。
为什么会出项这么多容器呢
因为每一个容器对对象的存储方式都有不同。即集合容器内部的数据结构不同。有多种具体容器不断向上抽取共性内容,就形成了集合框架。框架的顶层是collection
1添加
Boolean add(object c);
Boolean addAll(collection c);
2删除
Boolean remove(object c);//删除一个
Boolean removeAll(collection c);//删除一堆,和当前集合中相同的元素删除
例子:C1. removeAll(c2);返回布尔型
Viod clear();
3判断
Boolean Contains(object c);
Boolean ContainsAll(collection c);
Boolean isempty();
4获取
Int size();
Iterator Iterator();
调用集合中的迭代器方法,是为了获得迭代器对象。
Iterator it=Iterator.teretor();
While(it.hasNext()){
Syso(it.next());
}
运行完之后,迭代器it仍然存在,仍占用内存空间。我们把上述语句放到for循环当中就行了。
For(Iterator it=Iterator.terator();it.hasNext();){
Syso(it.next());
}
迭代器实现原理:
迭代器对象必须依赖于具体的容器,因为每一个容器的数据结构不同,所以该迭代器对象是在容器中内部实现的,对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器对象即可,也就是iterator方法。Iterator是所有collection容器进行元素出去的公共接口。
5其他
Boolean retainall(collection c);返回两个集合的交集
Object【】toarry(); //将集合转换成数组
Collection
--list 存入和取出的元素顺序一致,元素可以重复
---set元素不可以重复。无序。有可能有序。
List:特有方法,有一个共性特点就是可以操作角标。
1添加
Void add(index element)
Void add(index collection )
2删除
Object remove(index);
例子:public static void main(String[] args) {
ArrayList coll=new ArrayList();
coll.add("abc");
coll.add("123");
System.out.println(coll.remove(1));
}
结果是123
3修改
Object set(index,element)
4获取
Object get(index)
Int indexof(object)
Int lastindexof(object)
List sublist(from to)//获取子列表,包含头不包含尾。
例子:
public static void main(String[] args) {
ArrayList coll=new ArrayList();
coll.add("abc");
coll.add("123");
System.out.println(coll.get(3));
}
java.lang.IndexOutOfBoundsException:
List可以完成增删改查功能。
List list=new ArrayList();
List.Add(“abc1’);
List.Add(“abc2”);
List.Add(“abc3”);
Interator it=list.interator();
While(it.hasNext()){
//java.util.ConcurrentModificationException集合和迭代器同时对元素进行修改,引发的并发修改异常,可以使用Interator 接口的子接口ListIterator 来完成在迭代中对元素更多的操作。用list .listiterator();获取列表迭代器对象。
Object obj=it.next();
If(obj.equals(“abc2”)){
List.set(“abc8”);}
}
解决方式:
ListInterator it=list.Listinterator();
//实现在迭代过程中完成对元素的增删改查 是list特有的。
While(it.hasNext()){
Object obj=it.next();
If(obj.equals(“abc2”)){
it.set(“abc8”);}
}
List的子接口Listinterator中方法hasPrevious()是判定前一个元素;
List:
-----vector内部是数组数据结构。同步的,是安全的。效率低。
-----Arraylist内部是数组数据结构,是不同步的。效率高,替代了vector。查询快。
------linkedlist内部是链表结构的是不同步的。增删效率快。
Vector :
方法:加element的都是它本身特有的方法。
Int capacity();// 返回容量
vector特有的取出方法。
Vector v=new Vector();
v.addElement("abc1");
v.addElement("abc2");
Enumeration e=v.elements();
while(e.hasMoreElements()){
System.out.println(e.nextElement());
List接口:
List接口中的方法iterator()返回值是Iterator接口,接口中有两个方法,hasNext();next();用来输出集合中的元素。
Enumeration接口:
elements()是Vector类中的方法,返回值是Enumeration接口,接口中有两个方法可以实现对vector中元素的取出,是vector特有的取出方法。
此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。
Linkedlist:
Void Addfirst();Void Addlast();
Void getfirst();Void getlast();
Void removefirst();Void removelast();
例子;
While(!Link.isempty()){
Syso(link.removeFirst());
}
面试题:
请使用linkedlist来模拟一个堆栈或队列
队列:
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Vector;
import javax.swing.text.html.HTMLDocument.Iterator;
public class VectorDemo {
public static void main(String[] args) {
// 我们应该描述这样一个容器,给使用者提供一个容器对象完成这两种结构中的一种
Duilie d1=new Duilie();
d1.myAdd("abc1");
d1.myAdd("abc2");
d1.myAdd("abc3");
d1.myAdd("abc4");
while(!d1.isNull()){
System.out.println(d1.myGet());
}
}
}
class Duilie{
private LinkedList link;
Duilie(){
link=new LinkedList();
}
public void myAdd(Object obj){
link.addFirst(obj);
}
public Object myGet(){
return link.removeLast();
}
public boolean isNull(){
return link.isEmpty();
}
堆栈:
实现堆栈只需把removeLast()改为removeFirst()
Arraylist在开发中往往存放自定义对象,
ArrayList a=new ArrayList();
a.add(new Person("lisi",21));
a.add(new Person("wangwu",23));
a.add(new Person("xiaming",26));
Iterator it=a1.iterator();
while(it.hasNext()){
Person p=(Person) (it.next());//it.next()返回值是object类型,必须强转才能调用person中的方法
System.out.println(p.getName());
}
1.4版本以后有自动装箱功能。
ArrayList a=new ArrayList();
a.add(4);等价于a.add(new interger(4));
Set
元素是不可以重复的,无序。
set接口中的方法和collection一致。
------HashSet
内部结构是哈希表,是不同步的。
哈希值是通过一个算法得来的。
如何保证集合的元素是唯一的?
是通过对象的hashcode和equals方法来完成对象唯一性的。
如果两个元素的哈希值不同,那么不用判断两个对象的equals是否相同。直接存储到哈希表中。
如果两个元素的哈希值相同,再判断两个对象的equals是否为true。
如果为true,视为相同元素,不存,如果为false,就进行存储。
记住:如果元素要存储到hashset集合中,必须覆hashcode和equals方法。------TreeSet
可以对集合中的元素进行排序,是不同步的。
判断元素唯一性的方式: 就是根据比较方法的返回结果,如果返回的是0,不存。
Treeset对元素进行排序的方式一:
让元素自身具有比较功能,就需要实现comparable接口,覆盖compareto方法。
如果不要按照对象中具备的自然顺序进行排序,如果对象中不具备自然顺序,怎么办?
可以使用treeset集合第二种排序方式:
让集合自身具备比较功能,定义一个类,实现comparable接口,覆盖compare方法,将该类对象作为参数传递给treeset集合的构造函数。
Treeset底层数据结构是二叉排序树。
Map:
Map一次添加一对元素,collection一次添加一个元素,map也成为双列集合,collection又称单列集合,map中存的是键值对,map中必须保证健的唯一性。
常用方法:
1添加
Value put(key,value)返回前一个与key关联的值,如果没有返回null。
2删除
Void clear()清空map集合。
Value remove(key) 根据指定的健删除这个健的值。
3判断
Boolean containkey(key)
Boolean containkey(value)
Boolean isempty()
4获取
Value get(key)通过健获取值,如果没有该健返回null。
5 keyset()重点掌握
取出map中的所有元素
原理:
通过keyset方法取map中所有的健所在的set集合,再通过set的迭代器获取到每一个健,再对每一个健通过map集合的get方法获取对应的值即可。
Map<Integer,String> map=new HashMap<Integer,String>;
map.put(8,”wangwu”);
Set<Integer> ks=map. KeySet();
Interator<Integer> it=ks.iterator();
While(it.hasNext()){
Integer key=it.next();
String value=map.get(key);
Syso(key+value);
}
Entryset
该方法将建和值得映射关系作为对象存储到了set集合中,而这个映射关系的类型Map.Entry类型(结婚证)。
Set<Map.Entry<Integer,String>> entrySet=map.entrySet();
Intator<Map.Entry<Integer,String>> it=entrySet. Intator();
While(it.hasNext()){
Map.Entry<Integer,String> me=it.next();
Integer key=me.getKey();
String value=me.getValue();
Syso(key+value);
Values():
Collection<String> values=map.values();
Intator<String> it=values.intator();
While(it.hasNext()){
Syso(it.next());
Map常用子类:
--------hashtable内部结构是哈希表,是同步的,不允许空作为健,不允许空作为值(面试问和hashmap区别)
--------Properties:用来存储健值对型的配置文件的信息,可以和io技术结合使用。
-------hashmap内部结构是哈希表,是不同步的
-------treemap内部结构是二叉树,是不同步的,可以对map中的健进行排序。
Properties
特点:
1该集合中的健值都是字符串
2集合中的数据可以保存到流中,或者从流中获取。
应用:用于操作以健值对存在的配置文件。
配置文件:
存储信息的文件,这些信息是用于配置某些应用程序的。
配置文件有几种?
健值对的是一种。
Xml
数据库
用Properties存取键值对:
Properties prop=new Properties();
// 存储元素
Prop.setproperty(“zhangsan”,“30”);
Prop.setproperty(“liu”,“34”);
//修改元素
//Prop.setproperty(“zhangsan”,“26”);
//取出所有元素
Set<String> names=prop.stringPropertyName();//取出所有的健
For(String name:names){
//String value=prop.getProperty(name);由健获取值
Syso(name+value);
}
将键值对打印到控制台:
Properties prop=new Properties();
Prop.setproperty(“zhangsan”,“30”);
Prop.setproperty(“liu”,“34”);
Prop.list(System.out);//将健值对输出到指定的输出流
结果:zhangsan 30
Liu 34
使元素持久化(将内存中的数据保存到硬盘上):
Properties prop=new Properties();
//存储元素
Prop.setproperty(“zhangsan”,“30”);
Prop.setproperty(“liu”,“34”);
//想要将这些集合中的字符串健值信息持久化存储到文件(硬盘)中。
//需要关联的输出流。
FileOutputStream fos=new FileOutputStream(“a.txt”);
//将集合中的数据存储到文件中,使用store方法。
Prop.store(fos,”name+age”);
Fos.close();
结果:
在a.txt中有我们写的键值对
读取配置文件到控制台上:
集合中的数据来自于一个文件。
保证文件中的数据必须是键值对(文件必须是配置文件)。
需要使用到读取流。
Properties prop=new Properties();//集合
// 把a配置文件中的键值对放入输入流中。
FileInputStream fis=new FileInputStream (“a.txt”);
//使用load方法(从输入流中读取健值对)。
Prop.Load(fis);//从输入流中读取健值对,并把键值对存入到集合中。
Prop.list(system.out);//通过集合把键值对打印到控制台上
对已有的配置文件中的信息进行修改:
1读取这个文件
2并将这个文件中的健值数据存储到集合中。
3再通过集合对数据进行修改。
4再通过流将修改后的数据存储到文件中。
File file=new File(“a.txt”);
If(!File.exists()){
file.createNewFile();}
FileReader fr=new FileReader(file);//读取这个文件,把配置文件信息存入读取流中。
//创建集合存储配置信息。
Properties prop=new Properties();//创建集合
//从流中获得配置文件信息并将流中信息存储到集合中。
Prop.load(fr);
Prop.setProperty(“wangwu”,”16”);//修改语句
FileWriter file=new FileWriter (file);//写入流
Prop.store(fw,“”);//store() 方法 :将健值对写入输出流
//Prop.list(system.out);
Fw.close();
Fr.close();