您的位置:首页 > 其它

9 集合

2016-02-02 23:47 459 查看
collection接口
collection 接口方法

collection 迭代器

List接口

List接口的实现类
ArrayList

LinkedList

Vector

Set接口

Set接口的实现类
HashSet依靠equals和HashCode的方法共同作用

TreeSet

set集合中的equals和hashCode 转

创建String对象过程的内存分配转

Tips

小案例使用LinkedList实现洗牌

collection接口

集合接口的继承关系:

—-| Collection 单列集合 的根接口

——-| List 如果是实现了List接口的集合类,该集合类具备的特点:有序,可重复。

——-| Set 如果是实现了Set接口的集合类,该集合类具备的特点: 无序,不可重复。

collection 接口方法

//增
add(E e);
addAll(Collection<? extends E> c);
//删
clear();
remove(Object o);
removeAll(Collection<?> c);
//交集
retainAll(Collection<?> c);
//判断
contains(Object o);
containsAll (Collection<?> c);
equals(Object o);
isEmpty();
//迭代器
iteratior();
//大小
size();
//转换为数组
toArray();


collection 迭代器

Collection—迭代的方法:

toArray()

iterator()

迭代器的作用:就是用于抓取集合中的元素。

迭代器的方法:

hasNext()   问是否有元素可遍历。如果有元素可以遍历,返回true,否则返回false 。
next()    获取元素...
remove()  移除迭代器最后一次返回 的元素。


NoSuchElementException 没有元素的异常。

出现的原因: 没有元素可以被迭代了。。。

List接口

List接口中特有方法:

添加
add(int index, E element)
addAll(int index, Collection<? extends E> c)
获取:
get(int index)
indexOf(Object o)
lastIndexOf(Object o)
subList(int fromIndex, int toIndex)
修改:
set(int index, E element)

迭代
listIterator()


List接口中特有的方法具备的特点: 操作的方法都存在索引值

只有List接口下面的集合类才具备索引值。其他接口下面的集合类都没有索引值。

listIterator()

ListIterator特有的方法:

hasPrevious()  判断是否存在上一个元素。
previous()    当前指针先向上移动一个单位,然后再取出当前指针指向的元素。

next();  先取出当前指针指向的元素,然后指针向下移动一个单位。

add(E e)   把当前有元素插入到当前指针指向的位置上。
set(E e)   替换迭代器最后一次返回的元素。


迭代器注意事项

迭代器在变量元素的时候要注意事项: 在迭代器迭代元素的过程中,不允许使用集合对象改变集合中的元素个数,如果需要添加或者删除只能使用迭代器的方法进行操作

如果使用过了集合对象改变集合中元素个数那么就会出现ConcurrentModificationException异常。

迭代元素的过程中: 迭代器创建到使用结束的时间。

错误案例:

ListIterator it = list.listIterator();  //获取到迭代器
list.add("aa");//改变元素个数,将会出现错误
it.next();


while(it.hasNext()){
System.out.print(it.next()+",");
list.add("aa");  // add方法是把元素添加到集合的末尾处的。


正确使用:必须通过迭代器添加元素,因为迭代器指针会跳过通过迭代器添加的元素

while(it.hasNext()){
System.out.print(it.next()+",");
it.add("aa"); // 把元素添加到当前指针指向位置
}
//最后集合元素的输出
[张三, aa, 李四, aa, 王五, aa]


List接口的实现类

——| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。

—————| ArrayList ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。

—————| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。

—————| Vector(了解即可) 底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。

——| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。

ArrayList

List的实现类主要有三种:ArrayList LinkedList 和 Vector(不重要)

ArrayList:

ArrayList 底层是维护了一个Object数组实现的, 特点: 查询速度快,增删慢

什么时候使用ArrayList: 如果目前的数据是查询比较多,增删比较少的时候,那么就使用ArrayList存储这批数据

笔试题目: 使用ArrayList无参的构造函数创建一个对象时, 默认的容量是多少? 如果长度不够使用时又自增增长多少?

ArrayList底层是维护了一个Object数组实现的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍。

特有的方法:

ensureCapacity(int minCapaci上ty)//确保它至少能够容纳最小容量参数所指定的元素数
trimToSize()


LinkedList

特有方法:

addFirst(E e)
addLast(E e)

getFirst()
getLast()

removeFirst()
removeLast()


LinkedList实现数据结构

1:栈 (1.6) : 主要是用于实现堆栈数据结构的存储方式。

先进后出
push()
pop()


2:队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。

先进先出
offer()
poll()


返回逆序的迭代器对象

descendingIterator() 返回逆序的迭代器对象

Vector

笔试题: 说出ArrayLsit与Vector的区别?

相同点: ArrayList与Vector底层都是使用了Object数组实现的。

不同点:

1. ArrayList是线程不同步的,操作效率高。

Vector是线程同步的,操作效率低。

2. ArrayList是JDK1.2出现,Vector是jdk1.0的时候出现的。

Set接口

Set接口是无序的

无序: 添加元素 的顺序与元素出来的顺序是不一致的。

接口方法和collection 一致

Set接口的实现类

HashSet(依靠equals和HashCode的方法共同作用)

底层是使用了哈希表来支持的,特点: 存取速度快.

实现原理

往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 ,然后通过元素的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置。

情况1: 如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。

情况2: 如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行添加。

HashSet注意事项

HashSet是根据hashcode算出来的数值然后在哈希表中找相应的位置,如果某类是根据一个变量返回哈希值,如果修改了这个值,会影响remove的判断,如下

@Override
public int hashCode() {
return this.name.hashCode();
}

@Override
public boolean equals(Object obj) {
Book b  = (Book)obj;
return this.name.equals(b.name);
}


public static void main(String[] args) {
//不允许重复的书名存在。
HashSet<Book> books = new HashSet<Book>();
books.add(new Book("深入javaweb",34));
books.add(new Book("java神书",78));

//修改书名
Iterator<Book> it = books.iterator();
while(it.hasNext()){
Book b = it.next();
if(b.name.equals("java神书")){
b.name = "java编程思想";
}
}
//为什么修改名字之后不能删除了呢?
books.remove(new Book("java神书",78));
System.out.println("集合的元素:"+ books);
}


TreeSet

treeSet要注意的事项:

往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。

往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在compareTo(T o)方法上。

如果比较元素的时候,compareTo方法返回的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)

往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。

往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器, 那么是以比较器的比较规则优先使用

如何自定义定义比较器: 自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可。

自定义比较器的格式 :

class  类名  implements Comparator{

}


推荐使用:使用比较器(Comparator)。

TreeSet是可以对字符串进行排序 的, 因为字符串已经实现了Comparable接口。字符串的比较规则:

情况一: 对应位置有不同的字符出现, 就比较的就是对应位置不同的字符。

情况 二:对应位置上 的字符都一样,比较的就是字符串的长度。

set集合中的equals和hashCode (转)

hashCode默认是计算出对象的内存地址,可以自己改写,例如String类就改写了

Java 对equals方法和hashCode方法是这样规定的:

如果两个对象相同(使用equals比较,所以如果改写equals方法,一般也要改写hashCode方法),那么它们的hashCode值一定要相同;

如果两个对象的的hashCode相同,它们并不一定相同。(因为对于散列表来说每个位置是可能重复的)

hashCode和equals的比较:

equals的方法是给用户调用的,如果你想判断两个对象是否相等,你可以重写equals方法

hashCode方法一般不会让用户调用,比如hashmap中,由于Key是不可以重复的(equals和hashCode只要有一个不等即使不重复),它在判断key是不是重复的时候就判断了hashcode方法,而且也用到了equals方法。

创建String对象过程的内存分配(转)

String s = “abc”;

在class文件被JVM装载到内存中,JVM会创建一块String Pool,当执行这句话时,JVM首先在Pool中查看是否存在相同的字符串(使用equals比较),如果存在该对象,则不用创建新的字符串,而直接使用String Pool中已存在的对象“abc,然后将引用s指向String Pool中创建的对象。

String s = new String(“abc”);

首先在Pool中查看是否存在对象”abc”, 没有则创建,然后又在Heap创建一个新的对象,并赋给s.

如果Pool中存在,则不创建,然后在Heap中创建的对象.

即New一个String对象 相当于创建了两个对象(常量池中一个 heap中一个)

注意:new 两个String对象,即使内容相同,内存地址也不相同

Tips

循环可以加标号

outer: while(true)



break outer;

indexof 返回的是第一个

刚刚初始化的迭代器是不指向任何元素的

Random random = new random();

Random.nextint(大小) 这个范围不用减1,范围是0-大小

字符串转Int

Integer.parseInt

小案例:使用LinkedList实现洗牌

package cn.itcast.list;
import java.util.LinkedList;
import java.util.Random;

/*
需求: 使用LinkedList存储一副扑克牌,然后实现洗牌功能。
*/
//扑克类
class Poker{
String  color; //花色
String num; //点数
public Poker(String color, String num) {
super();
this.color = color;
this.num = num;
}
@Override
public String toString() {
return "{"+color+num+"}";
}
}
public class Demo2 {
public static void main(String[] args) {
LinkedList pokers = createPoker();
shufflePoker(pokers);
showPoker(pokers);
}
//洗牌的功能
public static void shufflePoker(LinkedList pokers){
//创建随机数对象
Random random = new Random();
for(int i = 0 ; i <100; i++){
//随机产生两个索引值
int index1 = random.nextInt(pokers.size());
int index2 = random.nextInt(pokers.size());
//根据索引值取出两张牌,然后交换两张牌的顺序
Poker poker1 = (Poker) pokers.get(index1);
Poker poker2 = (Poker) pokers.get(index2);
pokers.set(index1, poker2);
pokers.set(index2, poker1);
}
}
//显示扑克牌
public static void showPoker(LinkedList pokers){
for(int i = 0 ; i<pokers.size() ; i++){
System.out.print(pokers.get(i));
//换行
if(i%10==9){
System.out.println();
}
}
}
//生成扑克牌的方法
public static LinkedList createPoker(){
//该集合用于存储扑克对象。
LinkedList list = new LinkedList();
//定义数组存储所有的花色与点数
String[] colors = {"黑桃","红桃","梅花","方块"};
String[] nums = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
for(int i = 0 ; i < nums.length ; i++){
for(int j = 0 ; j<colors.length ; j++){
list.add(new Poker(colors[j], nums[i]));
}
}
return list;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: