集合框架
2016-02-29 14:25
260 查看
[align=left]集合框架接口和类很多,这里总结下常用的几个类和接口,以及一些常用的方法
[/align]
图1 集合框架继承关系图
注:本文的讲解顺序为图中的标号顺序。
1.增(add)
boolean add(E e)
boolean addAll(Collection<? extends E> c)
2.删除remove
void clear()
boolean remove(Object o)
boolean removeAll(Collection<?> c)
3.查询
boolean contains(Object o)
boolean containsAll(Collection<?> c)
boolean retainAll(Collection<?> c)
4.遍历
Iterator<E> iterator()
注:编辑集合框架元素的三大方法:
1.普通for循环
2.foreach
3.迭代器iterator
5.属性
boolean isEmpty()
int size()
6.定义自己的equals原则
boolean equals(Object o)
int hashCode()
7.转化为数组
Object[] toArray()
<T> T[] toArray(T[] a)
注:
①Collection的所有实现类都重写了toString()方法,所以输出对象是会按照一定模式输出
②Collection集合中添加元素时均被接受为Object类型
List底层数据操作集合是数组(可参见源码)
2.可重复性
元素每次存储的位置都是按照哈希算法来获取的。看似无序,但是是有一定规律的。所以每次需要重写插入类对象的hashCode()方法
2.不可重复性
即每次插入的元素不可以相同。这里需要重写从Object类中继承过来的方法equals(),定义自己的相等标准。
实例:
综上所述,为了遵守Set的两大特性:如果要往Set中加入元素,那么要重写此元素的hashCode()和equals()方法。因为在集合调用其add方法时,会首先根据hashCode判断插入位置是否相同,然后判断equals是否为true。此时重写的结果有四种可能
1.如果同为false,那么则可以顺利插入
2.hashCode为true,equals为false,那么此时会在hash表的某一个位置形成一个链式结构。
3.hashCode为false,equals为true,那么此时会在hash表的两个位置插入两个相同的对象。
4.hashCode为true,equals为true,那么此时不会进入哈希表。
显然,第2、3两种情况是很奇诡的,所以要求重写的hashCode()和equals()方法的结果应该保持一致。
LinkedHashSet
特点:可以根据插入时的顺序对所有元素进行遍历。
1.TreeSet中要求添加的元素为同一个类的实例
2.定义自己的排序规则:
①定制排序:加入到TreeSet中的类的实例需要先生成Comparator接口并且实现compare()方法,使得元素按照自己的预期排序。
②自然排序:加入到TreeSet中的类的实例需要实现Comparable接口并且实现compareTo()方法,使得元素按照自己的预期排序
只有满足了上面两个条件的之后才能被添加如TreeSet中。
注:添加元素时判断顺序:
①定制排序:compare->hashCode()->equals(),结果务必保持一致!
②自然排序:compareTo->hashCode()->equals(),结果务必保持一致!
推理过程和HashSet一致。
②并且对于每一条key-value对又被称作entry纪录。在Map接口中被封装成了Map.Entry
Map接口的方法可以分为:
1.增(add)
V put(K key, V value)
void putAll(Map<? extends K,? extends V> m)
2.删除remove
void clear()
V remove(Object key)
3.查询
boolean containsKey(Object key)
boolean containsValue(Object value)
V get(Object key)
4.遍历
Set<Map.Entry<K,V>> entrySet()
Collection<V> values()
Set<K> keySet()
5.属性
boolean isEmpty()
int size()
6.定义自己的equals原则
boolean equals(Object o)
int hashCode()
其余部分均可参见Set
Properties类:key和value均为String类型。
Collectios类:主要是对集合的元素进行操作比如排序Collections.sort(...),最为重要的是因为集合框架中比较常用的一些类:ArrayList、HashSet、TreeSet、HashMap、TreeMap等均为线程不安全的,如果要将他们转化为线程安全的,需要使用静态方法synchronizedXxx(),将其进行包装为线程安全 的。
HashMap和Hashtable的区别:HashMap线程不安全,效率较高,可以存放null-null键值对,但是Hashtable线程安全,效率较低,不可以存放null-null键值对
[align=left]
[/align]
[/align]
图1 集合框架继承关系图
注:本文的讲解顺序为图中的标号顺序。
一、接口
Collection接口
作为集合框架的根接口其方法大致可以分为七大类:1.增(add)
boolean add(E e)
boolean addAll(Collection<? extends E> c)
2.删除remove
void clear()
boolean remove(Object o)
boolean removeAll(Collection<?> c)
3.查询
boolean contains(Object o)
boolean containsAll(Collection<?> c)
boolean retainAll(Collection<?> c)
4.遍历
Iterator<E> iterator()
注:编辑集合框架元素的三大方法:
1.普通for循环
2.foreach
3.迭代器iterator
5.属性
boolean isEmpty()
int size()
6.定义自己的equals原则
boolean equals(Object o)
int hashCode()
7.转化为数组
Object[] toArray()
<T> T[] toArray(T[] a)
注:
①Collection的所有实现类都重写了toString()方法,所以输出对象是会按照一定模式输出
②Collection集合中添加元素时均被接受为Object类型
List接口
1.有序:List底层数据操作集合是数组(可参见源码)
2.可重复性
//实例程序: package com.heima.collection; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.junit.Test; public class ListTest { @Test public void testIterator() { List<Object> list=new ArrayList<Object>(); list.add(123); list.add(456); list.add("abc"); list.add("tcl"); // 遍历方法一 Iterator iterator=list.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } // 遍历方法二 for(Object o:list){ System.out.println(o); } // 遍历方法三 for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } } }
HashSet接口
1.无序性!=随机性元素每次存储的位置都是按照哈希算法来获取的。看似无序,但是是有一定规律的。所以每次需要重写插入类对象的hashCode()方法
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((birthday == null) ? 0 : birthday.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; }
2.不可重复性
即每次插入的元素不可以相同。这里需要重写从Object类中继承过来的方法equals(),定义自己的相等标准。
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Employee other = (Employee) obj; if (age != other.age) return false; if (birthday == null) { if (other.birthday != null) return false; } else if (!birthday.equals(other.birthday)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }
实例:
// 实例程序: /** * 无序性:根据hashCode函数获得存储位置 * 不可重复性:重写javaBean的hashcode同且equals */ @Test public void testHashSet() { Set<Object> set = new HashSet<Object>(); set.add(null); set.add(123); set.add("abc"); set.add(new Person("bb", 12)); set.add(new Person("bb", 12)); Iterator<Object> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } //Person.java package com.heima.collection; public class Person implements Comparable<Object>{ 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; } /*@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; }*/ @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; } public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public int compareTo(Object o) { if(o instanceof Person){ int i= ((Person) o).getAge()-this.age; if(i==0){ return ((Person) o).getName().compareTo(this.name); } return i; } return 0; }
综上所述,为了遵守Set的两大特性:如果要往Set中加入元素,那么要重写此元素的hashCode()和equals()方法。因为在集合调用其add方法时,会首先根据hashCode判断插入位置是否相同,然后判断equals是否为true。此时重写的结果有四种可能
1.如果同为false,那么则可以顺利插入
2.hashCode为true,equals为false,那么此时会在hash表的某一个位置形成一个链式结构。
3.hashCode为false,equals为true,那么此时会在hash表的两个位置插入两个相同的对象。
4.hashCode为true,equals为true,那么此时不会进入哈希表。
显然,第2、3两种情况是很奇诡的,所以要求重写的hashCode()和equals()方法的结果应该保持一致。
LinkedHashSet
特点:可以根据插入时的顺序对所有元素进行遍历。
TreeSet
TreeSet在原本Set的基础上还加上了一些特性:1.TreeSet中要求添加的元素为同一个类的实例
2.定义自己的排序规则:
①定制排序:加入到TreeSet中的类的实例需要先生成Comparator接口并且实现compare()方法,使得元素按照自己的预期排序。
@Test public void testTreeSetCompare() { Set set = new TreeSet(new Comparator() { public int compare(Object o1, Object o2) { if (o1 instanceof Person && o2 instanceof Person) { int i = ((Person) o1).getAge() - ((Person) o2).getAge(); if (i == 0) { return ((Person) o1).getName().compareTo( ((Person) o2).getName()); } return i; } return 0; } }); set.add(null); set.add(123); set.add("abc"); set.add(new Person("bb", 12)); set.add(new Person("bb", 13)); Iterator<Object> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
②自然排序:加入到TreeSet中的类的实例需要实现Comparable接口并且实现compareTo()方法,使得元素按照自己的预期排序
package com.heima.collection; public class Person implements Comparable<Object>{ 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; } /*@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; }*/ @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; } public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public int compareTo(Object o) { if(o instanceof Person){ int i= ((Person) o).getAge()-this.age; if(i==0){ return ((Person) o).getName().compareTo(this.name); } return i; } return 0; } }
@Test public void testTreeSet() { Set set = new TreeSet(); // set.add(123);//ClassCastException set.add(new Person("bb", 12)); set.add(new Person("bb", 12)); Iterator<Object> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
只有满足了上面两个条件的之后才能被添加如TreeSet中。
注:添加元素时判断顺序:
①定制排序:compare->hashCode()->equals(),结果务必保持一致!
②自然排序:compareTo->hashCode()->equals(),结果务必保持一致!
推理过程和HashSet一致。
HashMap
①Map接口可以看出是以Set为索引的List,即key为Set,value为类似于List。②并且对于每一条key-value对又被称作entry纪录。在Map接口中被封装成了Map.Entry
Map接口的方法可以分为:
1.增(add)
V put(K key, V value)
void putAll(Map<? extends K,? extends V> m)
2.删除remove
void clear()
V remove(Object key)
3.查询
boolean containsKey(Object key)
boolean containsValue(Object value)
V get(Object key)
4.遍历
Set<Map.Entry<K,V>> entrySet()
Collection<V> values()
Set<K> keySet()
5.属性
boolean isEmpty()
int size()
6.定义自己的equals原则
boolean equals(Object o)
int hashCode()
其余部分均可参见Set
Properties类:key和value均为String类型。
Collectios类:主要是对集合的元素进行操作比如排序Collections.sort(...),最为重要的是因为集合框架中比较常用的一些类:ArrayList、HashSet、TreeSet、HashMap、TreeMap等均为线程不安全的,如果要将他们转化为线程安全的,需要使用静态方法synchronizedXxx(),将其进行包装为线程安全 的。
HashMap和Hashtable的区别:HashMap线程不安全,效率较高,可以存放null-null键值对,但是Hashtable线程安全,效率较低,不可以存放null-null键值对
[align=left]
[/align]
相关文章推荐
- MyBatis持久化框架
- 点击发送后图片查看大图的实现思路
- 技术领导要不要写代码?
- Cesium.js 加载3D模型
- 离屏渲染学习笔记
- WCF简介
- 23种设计模式(17):备忘录模式
- OpenCV学习之阈值化
- SQL Server 不清空数据,修改数据库字段、结构,阻止保存要求重新创建表的更改
- springMVC+Java验证码完善注册功能
- Android - BroadcastRecevier
- redis学习
- jspwiki-2.10.1的权限配置与使用
- cesium 中地图发生了平移,放缩,旋转等动作所要执行的动作
- Android View坐标getLeft, getRight, getTop, getBottom
- 如何将jpg转换成pdf图片格式
- 浅谈web网站架构演变过程
- bootstrap基本html 模板
- Google推荐的图片加载库Glide介绍
- Apple Pay强势来袭,开发者应做的事情