一弧腥、對象流
對象流 序列化 公共流(節(jié)點(diǎn)流)
ObjectInputStream 反序列化輸入流 新增方法 readObject()
ObjectOutputStream 序列化輸出流 新增方法 writeObject()
注意:
先序列化后反序列化
輸入寫出的順序必須一致
不是所有的類都能夠序列化 實(shí)現(xiàn)接口java.io.Serializable
不是所有的屬性都需要序列化 transient
如果父類實(shí)現(xiàn)了序列化接口,子類中所有的內(nèi)容都與能力序列化
如果子類實(shí)現(xiàn)了序列化接口,但是父類沒有實(shí)現(xiàn),子類只能序列化自己的內(nèi)容
靜態(tài)的內(nèi)容不能序列化
public static void write(String dest,ArrayList<Student> stu) throws FileNotFoundException, IOException {
ObjectOutputStream oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
for(int i=0;i<stu.size();i++) {
System.out.println(stu.get(i));
oos.writeObject(stu.get(i));
}
oos.close();
}
public static boolean read(String src,int size) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new BufferedInputStream(new FileInputStream(src)));
ArrayList<Student> stu=null;
for(int i=0;i<size;i++) {
if("李凱".equals(((Student)(ois.readObject())).getName()))
return true;
}
ois.close();
return false;
}
二、潮太、容器: 可變長的,任意數(shù)據(jù)類型的數(shù)據(jù)的集合
1管搪、數(shù)組:
定長的
數(shù)據(jù)類型相同
有序,有索引,根據(jù)索引查詢效率高
缺點(diǎn):數(shù)組長度一旦確定,不可改變铡买,因此更鲁,不靈活:容量需要事先定義好,不能隨 著需求的變化而擴(kuò)容奇钞。
2澡为、容器類
數(shù)組遠(yuǎn)遠(yuǎn)不能滿足我們的需求。我們需要一種靈活的景埃,容量可以隨時(shí)擴(kuò)充的容 器來裝載我們的對象媒至。這就是容器類顶别,或者叫集合框架。
手寫簡單容器:
自定義容器類 : 只存儲字符串,實(shí)現(xiàn)隨著內(nèi)容的增刪長度可變
class MyContainer{
private String[] arr=null;
private int size;
public MyContainer() {
arr=new String[0];
}
public String getArr(int index) {
if(index<0||index>=size) {
throw new ArrayIndexOutOfBoundsException();
}
return arr[index];
}
public int getSize() {
return size;
}
/*
* 修改功能
*/
//添加
public void add(String str) {
String[] temp=arr;
arr=new String[size+1];
for(int i=0;i<size;i++) {
arr[i]=temp[i];
}
arr[size]=str;
size++;
}
//刪除
public void remove(int index) {
if(index<0||index>=size) {
throw new ArrayIndexOutOfBoundsException();
}
String[] temp=arr;
arr=new String[size-1];
for (int i = 0; i < temp.length; i++) {
if(i<=index) {
if(i==index)
continue;
arr[i]=temp[i];
}else {
arr[i-1]=temp[i];
}
}
size--;
}
}
3拒啰、集合 Collection
成員方法:
注意:
容器可以存儲任意類型的數(shù)據(jù)
泛型中的數(shù)據(jù)類型只能為引用類型,基本數(shù)據(jù)類型會發(fā)生非自動裝箱
遍歷:
增強(qiáng)for
迭代器
Collection col1 = new ArrayList();
Collection col2 = new ArrayList();
Collection<String> col3 = new ArrayList();
col1.add("123");
col1.add("567");
// boolean isEmpty() 如果此 collection 不包含元素驯绎,則返回 true。
System.out.println(col2.isEmpty());
// boolean addAll(Collection<? extends E> c)
// 將指定 collection 中的所有元素都添加到此 collection 中(可選操作)谋旦。
col2.addAll(col1);
System.out.println(col2);
// boolean contains(Object o)如果此 collection 包含指定的元素剩失,則返回 true。
System.out.println(col1.contains("123"));
// void clear() 移除此 collection 中的所有元素(可選操作)册着。
col1.clear();
System.out.println(col1.isEmpty());
// removeAll(Collection)
//移除此 collection 中那些也包含在指定 collection 中的所有元素(可選操作)拴孤。
System.out.println(col2.removeAll(col1));
System.out.println(col2);
// int size() 返回此 collection 中的元素?cái)?shù)。
System.out.println(col1.size());
// Object[] toArray() 返回包含此 collection 中所有元素的數(shù)組甲捏。
Object[] a = col1.toArray();
System.out.println(Arrays.toString(a));
//迭代器
Iterator it = col2.iterator();
if(it.hasNext()){
System.out.println(it.next());
}
//增強(qiáng)for
for(Object o:col2)
System.out.println(o);
4乞巧、 List接口:有序的,可重復(fù)的
新增功能:新增了一些關(guān)于索引操作的方法
接口遍歷:
for普通for
for .. each
迭代器
List<String> list=new ArrayList();
list.add("鋼鐵俠");
list.add("雷神");
list.add("鷹眼");
list.add("快銀");
list.add("浩克");
list.add("美國隊(duì)長");
list.add("洛基");
list.add("滅霸");
System.out.println(list);
//remove(ele|index) 如果數(shù)據(jù)和索引都是整數(shù),默認(rèn)把參數(shù)認(rèn)為index
list.remove(3);
System.out.println(list);
//List<E> subList(int fromIndex, int toIndex) toIndex取不到
System.out.println(list.subList(1, 3));
boolean flag=false;
for(int i=0;i<list.size();i++) {
if(list.get(i).equals("滅霸")) {
list.add("驚奇隊(duì)長");
}
}
System.out.println(list);
for(String str:list) {
if(str.equals("滅霸")) {
flag=true;
}
}
if(flag) {
list.add("驚奇隊(duì)長");
flag=false;
}
System.out.println(list);
for(Iterator it=list.iterator();it.hasNext();) {
if(it.next().equals("滅霸"))
flag=true;
}
if(flag) {
list.add("驚奇隊(duì)長");
}
System.out.println(list);
5、ArrayList :有序的可重復(fù)的
底層:數(shù)組實(shí)現(xiàn),進(jìn)行動態(tài)擴(kuò)容,每次使用copyOf方法進(jìn)行擴(kuò)容,每次擴(kuò)容后的容量是原容量的1.5倍
優(yōu)點(diǎn):隨機(jī)獲取或者遍歷效率高
缺點(diǎn):增刪效率低
線程不安全的,效率高
Vector: 向量
底層:數(shù)組實(shí)現(xiàn),使用copyOf方法進(jìn)行動態(tài)擴(kuò)容,每次擴(kuò)容后的容量是原容量的2倍
線程安全的,效率低
ArrayList<Person> al=new ArrayList<>();
al.add(new Person(1,"大錘",108));
System.out.println(al);
System.out.println(al.indexOf(new Person(1,"大錘",108)));
6摊鸡、LinkedList
底層:雙向鏈表實(shí)現(xiàn)
優(yōu)點(diǎn):做增刪效率高
缺點(diǎn):查詢和遍歷效率低
新增功能: 新增了一些操作與頭部和尾部的方法
LinkedList<String> ls=new LinkedList<String>();
ls.add("小明");
ls.add("小黃");
ls.add("小花");
System.out.println(ls);
//void addFirst(E e) 將指定元素插入此列表的開頭绽媒。
// void addLast(E e) 將指定元素添加到此列表的結(jié)尾。
ls.addFirst("1");
ls.addLast("0");
System.out.println(ls);
// E element() 獲取但不移除此列表的頭(第一個(gè)元素)免猾。
System.out.println(ls.element());
自定義LinkedList容器類(單向鏈表)
public class LinkedList05 {
public static void main(String[] args) {
//Test for MyLinkdeList
MylinkedList myll=new MylinkedList();
myll.add("assassin");
myll.add("sabor");
myll.add("berserker");
myll.add("lancer");
System.out.println(myll.getSize());
System.out.println(myll.get(3));
}
}
//自定義LinkedList容器類
class MylinkedList{
//鏈表頭
private Node head;
//鏈表長度
private int size;
//constructor
public MylinkedList() {}
//獲取長度
public int getSize() {
return size;
}
//獲取第index個(gè)數(shù)據(jù)
public String get(int index) {
Node temp=head;
for (int i = 0; i < size; i++) {
if(i==index) {
return temp.getData();
}else {
temp=temp.getAddress();
}
}
return null;
}
//添加元素
public void add(String str) {
//先創(chuàng)建一個(gè)新節(jié)點(diǎn)
Node newNode=new Node(str,null);
if(head==null) {
head=newNode;
size++;
}else {
Node temp=head;
for (int i = 0; i < size; i++) {
if(temp.getAddress()==null) {
temp.setAddress(newNode);
}else {
temp=temp.getAddress();
}
}
size++;
}
}
}
//節(jié)點(diǎn)類是辕,模擬單向鏈表,存儲數(shù)據(jù)和地址
class Node{
private String data;
private Node address;
public Node() { }
public Node(String data, Node address) {
super();
this.data = data;
this.address = address;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getAddress() {
return address;
}
public void setAddress(Node address) {
this.address = address;
}
}
7猎提、 Set 接口
無序的 不可重復(fù)
放入數(shù)據(jù)的順序和內(nèi)部真實(shí)存儲的順序不一致,內(nèi)部有自己的存儲順序,一旦確定了存儲順序不會發(fā)生改變
Set set=new HashSet();
set.add(1);
set.add(true);
set.add("qwer");
System.out.println(set);
//運(yùn)行結(jié)果[1, qwer, true]
8获三、HashSet
底層:哈希表結(jié)構(gòu)(數(shù)組+鏈表+紅黑樹)
優(yōu)點(diǎn):查詢,添加,刪除,修改效率高
缺點(diǎn):無序
注意:
如果兩個(gè)對象的hashcode值不相同,兩個(gè)對象肯定不相同,如果值相同,可能不是相同對象,可以是相同對象
HashSet<Person> hs=new HashSet<Person>();
hs.add(new Person(1,"張三",10));
hs.add(new Person(3,"趙四",22));
hs.add(new Person(3,"趙四",22));
System.out.println(hs);
//結(jié)果:
//[Person [id=3, name=二鍋頭, age=18],
//Person [id=3, name=趙四, age=22],
// Person [id=3, name=趙四, age=22]]
對對象類型數(shù)據(jù)進(jìn)行去重:要重寫hashCode和equals方法
先比較hashCode,如果值不同,不會調(diào)用equals方法,如果值相同才會調(diào)用equals方法
//重寫hashCode和equals方法后運(yùn)行結(jié)果:
//[Person [id=3, name=二鍋頭, age=18],
// Person [id=3, name=趙四, age=22]]
9、TreeSet
底層:紅黑樹
優(yōu)點(diǎn):升序排序
存放具有可比性的引用類型數(shù)據(jù)
TreeSet<Integer> ts=new TreeSet<Integer>();
ts.add(1);
ts.add(2);
ts.add(3);
System.out.println(ts);
TreeSet要求加入的所有元素都可以相互比較大小;可以控制比較位置來決定排序方向锨苏;hashset只能比較可相等不能比較大小
可以通過元素本身的類實(shí)現(xiàn)Comparable來自我解決
@Override
public int compareTo(Object o) {
if(this.id==((Person)o).getId()) {
return 0;
}else if (this.id>((Person)o).getId()) {
return -1;
}else {
return 1;
}
}
重寫之后可以使用自定義對象Person
TreeSet<Person> tsp=new TreeSet<Person>();
tsp.add(new Person(1,"張三",10));
tsp.add(new Person(3,"趙四",22));
tsp.add(new Person(3,"趙四",22));
System.out.println(tsp);
三疙教、Map
1、Map
實(shí)現(xiàn)Map接口的類用來存儲鍵(key)-值(value) 對伞租。
Map類中存儲的鍵-值對通過鍵來標(biāo)識贞谓,所以鍵值不能重復(fù)。
鍵值對:
存儲的數(shù)據(jù)都是key,value鍵值對形式的葵诈,二者之間為映射關(guān)系
key 可以任意數(shù)據(jù)類型 無序的,唯一的 -->set結(jié)合
value 可以任意數(shù)據(jù)類型 無序的 ,不唯一的 -->Collection結(jié)合
一個(gè)key只能對應(yīng)一個(gè)value(value可以為集合,集合中存儲多個(gè)數(shù)據(jù))
使用:
Map<String, Integer> map=new HashMap();
//添加元素 map.put("胡歌", 30);
map.put("胡歌", 28);//重復(fù)元素會覆蓋裸弦,因?yàn)槭前存I值判斷
map.put("劉德華", 50);
System.out.println(map);
//V get(Object key)
System.out.println(map.get("胡歌"));
//boolean containsKey(Object key) 如果此映射包含指定鍵的映射關(guān)系,則返回 true作喘。
//boolean containsValue(Object value)
System.out.println(map.containsKey("胡歌"));
//remove(key) System.out.println(map.remove("胡歌"));
運(yùn)行結(jié)果
{劉德華=50, 胡歌=28} 28 true 28
2理疙、HashMap
HashSet是由HashMap維護(hù)的,但是HashMap是鍵值對的形式,初始容量是16,加載因子是0.75
底層是hash表的結(jié)構(gòu)
HashMap的key如果是引用數(shù)據(jù)類型的對象,做去重要重寫hashCode和equals
如果想要實(shí)現(xiàn)value去重,需要手動判斷
HashMap<Person, Integer> hashmap=new HashMap();
hashmap.put(new Person(1,"趙",20),01);
hashmap.put(new Person(2,"錢",22),3); System.out.println(hashmap);
3、TreeMap
TreeSet是由TreeMap的key維護(hù)的,使用方式相同,但是是鍵值對的形式
//創(chuàng)建TreeMap對象 TreeMap<Person,Integer> tm1=new TreeMap();
//或調(diào)用有參構(gòu)造器泞坦,傳入比較器 TreeMap<Person,Integer> tm2=new TreeMap((o1,o2)->(((Person)o1).getAge()-((Person)o2).getAge()); tm1.put(new Person(1,"趙",20),01); tm2.put(new Person(2,"錢",22),3);
4窖贤、Properties
HashTable的子類,key和value都是string
Properties pp=new Properties(); // void load(InputStream inStream) 從輸入流中讀取屬性列表(鍵和元素對)。 pp.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties01")); System.out.println(pp.stringPropertyNames());
四赃梧、注意點(diǎn):
1择吊、繼承關(guān)系:Collection,Set槽奕,List几睛,Map都是接口,不能實(shí)例化粤攒,使用其實(shí)現(xiàn)類創(chuàng)建對象
2所森、ConcurrentModificationException 當(dāng)方法檢測到對象的并發(fā)修改,但不允許這種修改時(shí)夯接,拋出此異常焕济。