------- android培训、java培训、期待与您交流!----------
为了存储的存储和操作类对象,Java创建了集合框架:
集合框架包括两个接口Collection与Map,下图是集合框架个各类之间的关系:
1.Collection(能使用迭代器来遍历)
1.1List 有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
1.1.1 LinkedList 底层的数据结构是链表,线程不同步,增删元素的速度非常快。
1.1.2 ArrayList 底层的数据结构是数组,线程不同步,查询元素的速度非常快。
1.1.3 Vector 线程同步的,无论查询和增删都很慢,ArrayList替代了Vector。
1.2Set 无序,必须保证元素唯一性。
1.2.1 HashSet 底层数据结构是哈希表,线程是不同步的。无序,高效
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。 当元素的hashCode值相同时,才继续判断元素的equals是否为true。 如果为true,那么视为相同元素,不存。如果为false,那么存储。 如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。哈希表的原理:
1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。 2,哈希值就是这个元素的位置。
3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。
4,存储哈希值的结构,我们称为哈希表。
5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。 这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。
对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。
1.2.2 TreeSet 有序集合,不同步,TreeSet底层的数据结构就是二叉树。
插入TreeSet中的元素自身必须具备比较性,也就是要实现Coparable接口或Comparator接口
大于时返回正数,等于返回0,小于返回负数。
HashSet比TreeSet的查询速度快,因为TreeSet如果含有N个元素,平均要查询log2N次。
举个例子:当你要比较String的时候,你可以使用compareTo方法,它是按照字典顺序来对字符串进行比较,
当你对两个正整数比较的时候,可以直接返回他们的差值:
Class Item inplements Copareable<Item>
{
public int compareTo(Item other) //复写compareTo方法
{
return this.num - other.num;
}
}
import java.util.Comparator;
public class Student4Test10 implements Comparable
{
private String name;
private int age;
private double score;
public Student4Test10(String name, int age, double score)
{
this.name = name;
this.age = age;
this.score = score;
}
public String getName()
{
return name;
}
public double getAge()
{
return age;
}
public double getScore()
{
return score;
}
@Override
public int compareTo(Object o) {
Student4Test10 st = (Student4Test10)o;
//按成绩进行比较
if(this.score > st.score)
return 1;
else if (this.score == st.score) //当主要条件相同时比较次要条件
{
//成绩相同按照姓名排序,为什么不安年龄呢,String类有现成的比较方法,更简便
return this.name.compareTo(st.name) ;
}
return -1;
}
}
<p>/*
* 声明类Student,包含3个成员变量:name、age、score,创建5个对象装入TreeSet,
按照成绩排序输出结果(考虑成绩相同的问题)。
*/</p><p>package com.itheima;</p><p>import java.util.Iterator;
import java.util.TreeSet;</p><p>public class Test10 {
public static void main(String[] args) {
//创建一个TreeSet对象,并将元素类型规行为Student4Test10类型
TreeSet<Student4Test10> sTreeSet = new TreeSet<Student4Test10>();
// 添加元素
sTreeSet.add(new Student4Test10("H", 20, 91.5));
sTreeSet.add(new Student4Test10("M", 21, 90.5));
sTreeSet.add(new Student4Test10("C", 22, 80));
sTreeSet.add(new Student4Test10("X", 23, 80));
sTreeSet.add(new Student4Test10("Y", 24, 79));
//创建迭代器
Iterator<Student4Test10> it = sTreeSet.iterator();
//输出TreeSet中的元素
while(it.hasNext())
{
Student4Test10 st=(Student4Test10)it.next();
System.out.println(st.getName()+"的年龄是"+st.getAge()+"获得了"+st.getScore()+"分");
}
</p><pre class="java" name="code"><span style="font-size:18px;">2.集合中如何对元素进行操作</span>
2.1 Collection遍历方式
Collection 接口下的集合类都可以使用迭代器Iterator,它的另一种更优雅的写法是for-each循环
//创建迭代器 Iterator<Item> it = treeSet.iterator(); //输出TreeSet中的元素,假设Item是一个Student类,其中更有获得名字等的方法 while(it.hasNext()) { Item st=(Item)it.next(); System.out.println(st.getName()+"的年龄是"+st.getAge()+"获得了"+st.getScore()+"分"); }
此外,List下的类还具有特有的迭代器ListIterator。
2.1.1Iterator 与ListIterator的区别
Iterator只有三个方法,它只具有增、删的功能,只能对迭代器放过的元素(就是next()的)进行操作。
boolean | hasNext() 如果仍有元素可以迭代,则返回true。 |
E | next() 返回迭代的下一个元素。 |
void | remove() 删除上一个next()返回的元素,所以前面必须有next() |
ListIterator 拥有很多方法,增删改查样样精通
增:
void | add(E e) 将指定的元素插入列表(可选操作)。 |
删:
void | remove() 从列表中移除由next 或previous 返回的最后一个元素(可选操作)。 |
改:
void | set(E e) 用指定元素替换next 或previous 返回的最后一个元素(可选操作)。 |
查:
E | next() 返回列表中的下一个元素。 |
E | previous() 返回列表中的前一个元素。 |
2.1.2List和Set的常用方法:
Set的常用方法:
由于Set的查询效率很低,所以我们一般利用地是他的增查操作,查询操作就是他的迭代
boolean | add(E e) 如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。 |
void | clear() 移除此 set 中的所有元素(可选操作)。 |
boolean | contains(Object o) 如果 set 包含指定的元素,则返回true。 |
Iterator<E> | iterator() 返回在此 set 中的元素上进行迭代的迭代器。 |
boolean | remove(Object o) 如果 set 中存在指定的元素,则将其移除(可选操作)。 |
int | size() 返回 set 中的元素数(其容量)。 |
List中除了上面几种方法还有几种特有的方法,大部分是上面的方法加上要操作的角标
void | add(String item, int index) 向滚动列表中索引指示的位置添加指定的项。 |
String | getItem(int index) 获取与指定索引关联的项。 |
void | remove(int position) 从此滚动列表中移除指定位置处的项。 |
2.1.3 Collection转为数组的两种方法
toArray();,返回的是Object[], 且类型不可转换
toArray(new String[*.size()]),返回指定的操作类型,建议使用
2.2 Map的取出方式
Map不具备迭代器,添加时put不是add
Map就有三个视图:
2.2.1 键集:键值唯一性 取出方法为
Set<K> | keySet() 返回此映射中包含的键的Set 视图。 |
2.2.2 值集合:必须获得对应的键值才能够获得值,所以可以先遍历键值,然后获得值
V | get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null 。 |
2.2.3 键/值对映射关系
Set<Map.Entry<K,V>> | entrySet() 返回此映射中包含的映射关系的Set 视图。 |
它返回的是Set集合,所以可以迭代,返回的值类型是Map.Entry<>,就有取出键和值的方法:
getKey()与getValue()
//HashMap的练习
Map<String,String> staff = new HashMap<String, String>();
staff.put("111", "aaa");
staff.put("222", "bbb");
staff.put("333", "ccc");
//打印出所有键值关系
System.out.println(staff);//{111=aaa, 222=bbb, 333=ccc}
//删除一个键,对应的值也就删除了
staff.remove("111");
//将某一个值进行替换,并获得这个键对应的值
staff.replace("222", "b");
staff.get("111");
// 迭代映射关系
for(Map.Entry<String, String> entry : staff.entrySet())
{
String key = entry.getKey();
String value = entry.getValue();
System.out.println("key"+key+"value"+value);
}