java学习之集合框架
集合类的由来: 对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储。 集合的特点: 1、用于存储对象的容器。 2、集合的长度是可变的。 3、集合中不可以存储基本数据类型值。
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储。
集合的特点:
1、用于存储对象的容器。
2、集合的长度是可变的。
3、集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体的容器,不断的向上抽取,就形成了集合框架。
集合框架图:
框架的顶层Collection接口:
Collection的常见方法:
1、添加
boolean add(Object obj);
boolean addAll(Collection coll);
2、删除
boolean remove(Object obj); 会改变集合长度
boolean removeAll(Collection coll);
void clear();
3、判断
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty(); 判断集合中是否有元素
4、获取
int size();
Iterator iterator(); 取出元素的方式:迭代器的对象必须依赖于具体容器,因为每一个容器的数据结构不同,
所以该迭代器对象是在容器中进行内部实现的。
对于使用容器者而言,具体的实现不重要,只要通过容器过去到该实现的迭代器的对象即可,也就是iterator方法。Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
5、其他
boolean retainAll(Collection coll); 取交集
Object[] toArray(); 将集合转成数组。
Collection
---List:有序(存入和取出的顺序一致),元素都有索引,元素可以重复。
---Set:元素不能重复,无序。
List:特有的常见方法,有一个共性特点就是都可以操作角标。
1、添加
boolean add(E e);
void add(int index, E element);
2、删除
Object remove(int index);
3、修改:
Object set(int index, E element)
4、获取:
Object get(int index);
int indexOf(object);
int lastIndexOf(object);
List subList(int fromIndex, int toIndex);
public static void showMethod1(List list)
{
//添加元素
list.add("asd1");
list.add("asd2");
list.add("asd3");
System.out.println(list);//[asd1, asd2, asd3]
//插入元素
list.add(1, "asd4");
System.out.println(list);//[asd1, asd4, asd2, asd3]
//删除元素
System.out.println("remove = " + list.remove(0));//remove = asd1
System.out.println(list);//[asd4, asd2, asd3]
//修改元素
System.out.println("set = " + list.set(1, "asd5"));//set = asd2 返回被修改的那个
System.out.println(list);//[asd4, asd5, asd3]
//获取元素
System.out.println("get = " + list.get(0));//get = asd4
//获取子列表
System.out.println("subList = " + list.subList(1, 2));//subList = [asd5]
}
取出元素方法:
public static void showMethod2(List list)
{
list.add("asd1");
list.add("asd2");
list.add("asd3");
list.add("asd4");
Iterator it = list.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
//List特有的取出元素的方式之一
for(int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}
}
list集合是可以完成对元素的增删改查
List:
---Vector:内部是数组数据结构,是同步的(线程是安全的)。增删,查询都很慢。
---ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。
---LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。
LinkedList:
addFirst();
addLast();
JDK1.6后
offerFirst();
offerLast();
getFirst();//获取但不移除,如果链表为空,抛出NoSuchElementException
getLast();
JDK1.6后
peekFirst();//获取但不移除,如果链表为空,返回null
peekLast();
removeFirst();获取并移除,如果链表为空,抛出NoSuchElementException
removeLast();
JKD1.6后:
pollFirst();//获取并移除,如果链表为空,返回null
pollLast();
LinkedList练习代码:
public static void main(String[] args)
{
LinkedList link = new LinkedList();
//往链表头添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
Iterator it = link.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
System.out.println(link);//[abc4, abc3, abc2, abc1]
System.out.println(link.getFirst());//abc4 取得链表头元素,但不删除
System.out.println(link.getLast());//abc1 取得链表尾元素,但不删除
System.out.println(link.removeFirst());//abc4 删除链表头元素,返回被删除的元素
System.out.println(link.removeFirst());//abc3
System.out.println(link);//[abc2, abc1]
//利用removeFirst取得链表中的每个元素,但是结束后链表变为空
while(!link.isEmpty())
{
System.out.println(link.removeFirst());
}
System.out.println(link);//[]
}
Set:元素不可以重复,是无序的。
Set接口中的方法和Collection一致
|---HashSet:内部数据结构是哈希表,是不同步的。
如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存入。如果为false,那么视为不同元素,就进行存储。
|---TreeSet:可以对Set集合中的元素进行排序,是不同步的。
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,如果是0就是相同元素,不存储。
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,元素需要实现Comparable接口,覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合的排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator(比较器)接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
Set集合输出顺序和存入的顺序不一致。第五行和第八行都把字符串"xixi"添加到集合中,但是Set集合不能
存放相同的元素,所以没有添加进去。
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add("haha");
hs.add("xixi");
hs.add("hehe");
hs.add("heihei");
hs.add("xixi");
Iterator it = hs.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
/*输出
* haha
* heihei
* xixi
* hehe*/
}
1、判断的是两个元素的哈希值是否相同。
如果相同,再判断两个对象的内容是否相同。
2、判断哈希值相同,其实判断的是对象的hashCode方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals的。
用哈希表存储自定义对象时,一般需要覆盖其父类Object中的hashCode方法和equals方法,构造自己的判断是否相同的方式。
如果哈希表要保证存入和输出有序,那可以使用HashSet的子类LinkedHashSet
Map:一次添加一对元素。Collection一次添加一个元素
Map也称为双列集合,Collection集合称为单列集合。
其实Map集合中存储的就是键值对,必须保证键的唯一性。
常用方法:
1、添加:
value put(key, value);返回前一个和key关联的值,如果没有返回null
2、删除:
void clear();清空Map集合
value remove (key);根据指定的key删除这个键值对
3、判断:
boolean containsKey(key);
boolean containsValue(value);
boolean isEmpty();
4、获取:
value get(key);通过键获取值,如果没有该键,返回null。可以通过返回null,来判断是否包含指定键。
int size();获取键值对的个数。
public static void method1(Map<Integer, String> map)
{
//添加元素
System.out.println(map.put(8, "wangcai"));//null 没有原来值,返回null
System.out.println(map.put(8, "xiaoqiang"));//wangcai 替换了原来的值,返回原来的值
map.put(2, "zhangsan");
map.put(5, "wangwu");
System.out.println(map);//{2=zhangsan, 5=wangwu, 8=xiaoqiang}
//删除
System.out.println("remove:" + map.remove(2));//remove:zhangsan
//判断
System.out.println("comtainskey:" + map.containsKey(5));//comtainskey:true
//获取
System.out.println("get:" + map.get(8));//get:xiaoqiang
}
获取map中的元素方式一:
private static void method2(Map<Integer, String> map)
{
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
//取出map中的所有元素。
//原理:通过keySet方法获取map中所有的键所在的Set集合,再通过Set的迭代器
//获取到每一个键,再对每一个键获取其对于的值即可。
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext())
{
Integer key = it.next();
System.out.println(map.get(key));
/*zhangsan
xiaohong
wangwu
zhaoming*/
}
}
获取map中的元素方式二:
private static void method3(Map<Integer, String> map)
{
/*
* 通过Map转成Set就可以迭代,找到另一个方法entrySet
* 该方法得到键和值的映射关系作为对象存储到了Set集合中,
* 而这个映射关系的类型就是Map.Entry类型。
*/
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
while (it.hasNext())
{
Map.Entry<Integer, String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key + " : " + value);
}
/*
* 5 : zhangsan
* 7 : xiaohong
* 8 : wangwu
* 9 : zhaoming
*/
}
获取map中的元素方式三:
private static void method4(Map<Integer, String> map)
{
map.put(8, "wangwu");
map.put(5, "zhangsan");
map.put(7, "xiaohong");
map.put(9, "zhaoming");
Collection<String> values = map.values();
Iterator<String> it = values.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
/*zhangsan
xiaohong
wangwu
zhaoming*/
}
集合的一些技巧:
需要唯一吗?
需要:Set
需要指定顺序吗?
需要:TreeSet
不需要:HashSet
但是想要一个和存储一直的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
如何记住每一个容器的结构和所属体系?看容器名字
List:
|---ArrayList
|---LinkedList
Set:
|---HashSet
|---TreeSet
后缀名就是该集合所属的体系,前缀名就是该集合的数据结构。
看到array就要想到数组,就要想到查询快,有下标
看到link就要想到链表,就要想到增删快,就要想到add get remove + frist last的方法
看到hash就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashCode方法和equals方法
看到tree就要想到二叉树,就要想到排序,就要想到两个接口Comparable,Comparator接口
而且通常这些常用的集合容器都是不同步的。
更多推荐
所有评论(0)