黑马程序员----java集合
来源:互联网 发布:在哪看淘宝达人的帖子 编辑:程序博客网 时间:2024/05/17 23:00
---------------------- ASP.Net+Unity开发 .Net培训 期待与您交流! ----------------------
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都不同。这个存储方式称之为:数据结构。
Collection
顶级接口public boolean add(E e)
public boolean addAll(Collection<? extends E> c)
public void clear() ;//清空
public boolean remove(Object o)
public boolean removeAll(Collection<?> c)
//去除指定集合c与本身集合都有的元素,去交集
public boolean contains(Object o)
public boolean isEmpty()
public int size() ;
public boolean retainAll(Collection<?> c)
//仅保留此collection中那些也包含在指定collection中的所有元素
//取交集
public Object[] toArray()
public Iterator<E> iterator()
迭代器
1,add方法的参数类型就是Object,以便于接受任意类型对象。
2,集合中存储的都是对象的引用
Iterator接口
hasNext()next()
remove()
把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素。
那么取出方式就被定义成了内部类;而每一个容器的数据结构不同,所以取出的
动作细节也不一样。但是都有共性内容[就是判断和取出]。那么可以将这些共性抽取出来。
这些内部类都符合一个规则。抽象成一个接口:Iterator接口。
如何获取集合的取出数据对象呢?
通过一个对外提供的方法: iterator();
迭代器的for循环
for(Iterator it=arrayList.iterator(); it.hasNext(); ){
System.out.println(it.next());
}
Collection 的常见子接口:
List, Set|List:集合的特点:元素是有序的,元素是可以重复的,
| 因为该集合体系有索引。
|Set:集合的特点:元素是无序的,元素是不可以重复的,
| 该集合体系没有索引。
List中的特有方法:
凡是可以操作脚标的方法都是该体系特有的方法:增
public void add(int index, E element);
public void addAll(index, Collection)
删
public E remove(int index)
改
public set(index,element)
查
public E get(int index)
public List<E> subList(int fromIndex, int toIndex);
返回列表中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图。
public int indexOf(Object o)
获取元素的脚标
public int lastIndexOf(Object o)
public ListIterator<E> listIterator(int index)
列表迭代器
在迭代器迭代过程中,如果对数据进行了增删改操作,会出现
java.util.ConcurrentModificationException:(并发修改异常:当方法检测到对象的并发修改,但不允许这种修改,抛出此异常.)
所以在迭代过程中,只能用迭代器的remove() 方法
ListIterator(列表迭代器)
list集合特有的迭代器。ListIterator是Iterator的子接口在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生并发修改异常。
所以,在迭代时,只能使用迭代器的方法来操作元素,可以Iterator方法是有限的,
如果想要其他的操作,如添加,修改等,就需要使用其子接口,ListIterator;
该接口只能通过List集合的 方法 listIterator() 来获取
public boolean hasNext()
public E next()
public boolean hasPrevious()
public E previous()
public int previousIndex()
public int nexIndex()
public void add(E e)
public void remove()
public void set(E e)
List常见实现类
|ArrayList: 底层使用的是数组结构;特点:查询速度很快,增删改的速度慢。不同步的|LinkedList: 底层使用的是链表数据结构;特点:查询速度慢,增删改的速度快。不同步
|Vector: 底层使用是数组结构;Vector是同步的。被ArrayList替代了
Vector 中的一个比较特别的方法:
public Enumeration elements();
//枚举就是Vector特有的取出元素遍历的方式,枚举和迭代器的方式很像
//其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长,所以
//被迭代器取代了。
eg: Enumeration en = vector.elements();
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
LinkedList的一些特有的方法
addFirst();
addLast();
getFirst(); //获取但是不删除第一个元素,如果集合中没有元素时会抛出异常NoSuchElementException。
getLast(); //获取但是不删除最后一个元素,如果集合中没有元素时会抛出异常。
removeFirst(); //获取并且删除第一个元素,如果集合中没有元素时会抛出异常。
removeLast(); //获取并且删除最后一个元素,如果集合中没有元素时会抛出异常。
版本1.6才出现这个方法
offerFirst() 添加元素
offerLast()
peekFirst()
peekLast()
public E pollFirst(); 获取并移除第一个元素,如果此列表为空,则返回null.
public E pollLast();
重点:1.问题:使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出
队列:先进先出
2.问题:去除ArrayList集合中的重复元素
List集合判断元素是否相同,使用的是元素的equals方法来进行判断。
Set:
元素是无序(存入和取出的顺序不一定一致),而且元素不可以重复
Set集合的方法和Collection的方法是一致的。|HashSet: 底层的数据结构是哈希表,线程是非同步的。
|TreeSet:
HashSet存储自定义对象,自定义对象需要重写 equals()方法,hashCode()方法。
用于保证存入set集合中的元素的惟一性。
当一个对象存入到集合中时,先用hashCode() 方法确定 hashCode值,
如果hashCode值不同,不会调用equals()方法;
如果hashCode值相同,才会调用equals()方法来判断两个对象是否相同,如果相同则不放入到集合中。
注意细节:
public int hashCode(){} //返回的是int
public boolean equals(Object obj) //接收的参数是Object
hashSet的contains(), remove() 等方法的判断和删除依据,
依然是先判断hashCode(),然后调用equals()方法
TreeSet:
可以对Set集合中的元素进行排序,底层的数据结构是二叉树。
没有指定排序方式时是按照自然顺序来排序。自定义对象 存入到TreeSet中时,可能会抛出java.lang.ClassCastException异常。
自定义对象需要实现java.lang.Comparable接口,才不会出现异常。
public interface Comparable<T>
此接口强行对实现它的每一个类的对象进行整体排序。这种排序被称为类的自然排序。
类的compareTo()方法被称为它的自然比较方法。
public int compareTo(Object obj){}
//当通过compareTo()方法判断两个对象相等时,会被认为是重复元素,会导致该对象无法存入到集合中。
注意:
排序时,当主要条件相同时,一定要判断一下次要条件。
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet排序的第二种方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
构造器
TreeSet(Comparator<? super E> comparator )
构造一个新的空TreeSet,它根据指定比较器进行排序。
当2种排序都存在时,以集合的比较器为主。
练习: 1,按照字符串长度排序。
泛型:
jdk1.5出现的新特性,用于解决安全问题,是一个类型安全机制。
通常在集合框架中很常见当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
泛型的好处:
1.将运行时期出现的问题ClassCastException,转移到了编译时期,
方便了程序员解决问题,让运行时的问题减少,程序更安全
2.避免了强制转换的麻烦
泛型的格式:通过<>来定义要操作的引用类型。
如何在自定义类中使用泛型?
1.泛型可以定义在类上
public class Demo<T>
2.为了让一个类中的不同方法可以操作不同类型对象,而且类型不确定。
那么可以将泛型定义在方法上。
public <T> void show(T t)
3.泛型类和泛型方法可以应用在同一个类中,只要定义不同的标识类型
4.注意:泛型只有在确定对象实例时才能确定类型;静态方法不可以访问类上定义的泛型;
如果静态方法操作的应用数据类型不确定,可以将泛型定义在静态方法上。
//静态方法定义泛型注意格式
public static <T> void method(T t){}
5.泛型定义在接口上
public Interface Inter<T>{
void show(T t);
}
然后定义类实现接口
class InterImpl implements Inter<String>{
public void show(String t){...}
}
如果定义类实现接口时也不能确定类型,那么需要写成
class InterImpl<T> implements Inter<T>{
public void show(T t){.......}
}
泛型限定
泛型中的通配符 : ?? extends E E以及E的继承类;上限
? super E E以及E的父类;下限
泛型限定是用于泛型扩展用的
Map集合
1,存储键值对。而且要保证 键 的惟一性。2, map集合没有迭代器
Map集合的通用方法
增
public V put(K key, V value);
//存入键值对,
//如果添加时出现相同的键,那么后添加的值会覆盖原来键对应值,返回原来的值。
//否则返回null
public void putAll(Map<? extends K, ? extends V> m)
删
public void clear();
public V remove(Object key)
判断
public boolean containsKey(Object key) //是否包含指定的 键
public boolean containsValue(Object value)
public boolean isEmpty()
获取
public V get(Object key) //返回指定键所映射的值;此映射不包含该键,返回null
public int size()
public Collection<V> values() //得到所有的值
public Set<Map.Entry<E,V>> entrySet()
//返回此映射包含的映射关系的Set视图
//Map的内部接口:Map.Entry
//Map.Entry其实Entry是Map接口中的一个静态内部接口。
// public static interface Map.Entry<K,V>
// 能加static修饰的接口一定是内部接口
public Set<K> keySet()
//将map中所有的键存入一个set集合中
Map 常用的子类
|--Hahstable|--HashMap
|--TreeMap
Set底层就是使用的Map集合。
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable
1.底层是哈希表数据结构,
2.不可以存入null键 null值
3.线程同步的
4.用作键的对象必须实现hashCode方法和equals() 方法
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable,Serializable
1.底层是基于哈希表的数据结构
2.允许使用null健 ,null值
3.线程非同步的
4.不保证映射的顺序,特别是它不保证该顺序恒久不变
5.注意:除了非同步和允许使用null之外, HashMap和hashtable大致相同;
jdk1.2才出现hashmap,jdk1.0 就有hashtable了
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, Serializable
1.基于红黑树的NavigableMap实现;底层就是二叉树数据结构
2.线程不同步。可以用于给Map集合中的键进行排序。
hashMap集合中键可以为null,而且唯一。
可以通过get方法的返回值来判断一个键是否存在。
对hashMap的遍历
//1.第一种遍历方式 //获得所有键的Set集合 Set<String> keySet = map.keySet(); //有了Set集合,就可以取得迭代器 Iterator<String> it = keySet.iterator(); while(it.hasNext()){ System.out.println("value:" +hashMap.get(it.next())); }
//2.第二种遍历方式
Set<Map.Entry<String,String>> entrySet = map.entrySet(); Iterator<Map.Entry<String, String>> it = entrySet.iterator(); while(it.hasNext()){ Map.Entry<String,String> me =it.next(); String key = me.getKey(); String value= me.getValue(); System.out.println("key :" + key + ", value" + value); }
练习1:
每一个学生都有对应的归属地
学生 Student,地址String
学生属性:姓名,年龄
注意:姓名和年龄相同的视为一个学生
保证学生的惟一性
1,描叙学生
2,定义map容器,将学生作为键,地址作为值,存入。
3,获取map集合中的元素。
//知识点:equals方法中抛出类型不匹配异常
// .. public boolean equals(Object obj){ if(! (obj instanceof Student)){ throw new ClassCastException("类型不匹配"); } } // ...
自定义的Student类需要实现hashCode(),equals()方法,并需要Comparable接口
练习2:
对学生对象的年龄进行升序排序
因为数据是以键值对形式存在的。
所以要使用可以排序的Map集合。TreeMap。
练习3:
“sadfsadgsadgsa” 获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2)....
Map集合的扩展知识
map集合被使用是因为具备映射关系
map集合的嵌套
例如;一个学校有多个教室,一个教室有多个学生
集合的工具类 Collections
方法:
public static <T extends Comparable<? super T>> void sort(List<T> list)
//根据元素的自然顺序对指定列表按升序进行排序。
public static <T> void sort(List<T> list, Comparator<? super T> c)
//根据指定比较器产生的顺序对指定列表进行排序。
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
//根据元素的自然顺序返回给定collection的最大元素。
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
//使用二分搜索法搜索指定列表,以获得指定对象。
//但凡使用binarySearch,集合必须是已经排好序的。
//返回指定的元素的索引
public static <T> void fill(List<? super T> list, T obj);
//使用指定元素替换指定列表中的所有元素
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal);
//使用另一个值替换列表中出现的所有某一指定值
public static void reverse(List<?> list)
//反转指定列表中元素的顺序,
public static <T> Comparator<T> reverseOrder()
//返回一个比较器,它强行逆转实现了Comparable接口的对象collection的自然顺序。
//eg:
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
//返回一个比较起,它强行逆转指定比较起的顺序。
//如果指定比较起为null,则此方法等同于reverseOrder
public static void swap(List<?> list, int i, int j)
//在指定列表的指定位置处交换元素
public static void shuffle(List<?> list)
//随机对列表中的元素的位置重新洗牌
//让集合支持同步
public static <T> Collection<T> synchronizedCollection(Collection<T> c)
//返回指定collection支持的同步(线程安全的)collection
public static <T> List<T> synchronizedList(List<T> list)
//返回指定列表支持的同步(线程安全的)列表
public static <E,V> Map<E,V> synchronizedMap(Map<K,V> m)
.........
Arrays: 用于操作数组的工具类,里面都是静态方法
public static <T> T[] copyOfRange(T[] original, int from, int to)
//将指定数组的指定范围复制到一个新数组,不包括to索引位置的元素
public static boolean equal(Object[] a, Object[] a2);
//如果两个指定的Objects数组彼此相等,则返回true;
public static boolean deepEquals(Object[] a1, Object[] a2)
//如果两个指定数组彼此是深层相等的,则返回true
public static void fill(Object[] a, Object val);
//将指定的Object应用分配给指定Object数组的每个元素。
public static void fill(Object[] a, int fromIndex, int toIndex, Object val);
// 将指定的Object应用分配给指定Object数组的指定范围的元素。
public static void sort(T[])
public satic String toString(T[] a)
//返回指定数组内容的字符串表现形式
public static <T> List<T> asList(T... a)
//返回一个受指定数组支持的固定大小的列表,将数组转换成List集合
//注意:将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定的
//否则会抛出异常UnsupportedOperationException
//
//如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
//如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
//集合转换成数组
Colleciton中的
public <T> T[] toArray(T[] a);
//接受一个数组参数,指定类型的数组的长度要定义多长呢?
//当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新的数组,长度为集合的size
//当指定类型的数组的长度大于集合的size,就不会新创建数组了,而是使用传递进来的数组。
eg: ........
String[] arr = arrayList.toArray(new String[arrayList.size()]);
System.out.println(Arrays.toString(arr));
//为什么要将集合转换成数组?
为了限定对元素的操作。
1.5版本开始一个新的接口 public interface Iterable<T> 增强for
//实现这个接口允许对象成为“foreach”语句的目标。//接口的方法:
public Iterator<T> iterator()
//返回一个在一组T类型的元素上进行迭代的迭代器
传统for和高级for有什么区别呢?
高级for有一个局限性,高级for必须有一个被遍历的目标。
建议遍历数组的时候,依然使用传统for,可以使用索引。
1.5出现的一个新特性: 可变参数
其实就是数组参数的简写形式。
不用每一次都手动的建立数组对象。
只要将要操作的元素作为参数传递即可
隐式的将这些参数封装成数组。
注意:可变参数一定要定义在参数列表的最后边。
1.5版本的新特性: 静态导入
静态导入导入的全部是一个类中的静态成员(静态方法,静态属性.......)
eg: import static java.util.Arrays.*; //导入的是Arrays这个静态工具类中的所有静态成员
import static java.lang.System.*; //导入了System类中的所有静态成员
//当类名重名时,需要指定具体的包名
//当方法重名时,需要指定所属的对象或者类。
---------------------- ASP.Net+Unity开发 .Net培训 期待与您交流! ----------------------
0 0
- 黑马程序员 java 集合
- 黑马程序员---java集合
- 黑马程序员---集合【java】
- 黑马程序员-------Java集合
- 黑马程序员-java集合
- 黑马程序员--Java集合
- 黑马程序员----java集合
- 黑马程序员----JAVA集合
- 黑马程序员--Java集合
- 黑马程序员--java集合
- 黑马程序员--java集合
- 黑马程序员---java---集合
- 黑马程序员Java----集合
- 黑马程序员 JAVA集合
- 黑马程序员-Java集合
- 黑马程序员-java集合
- 黑马程序员--Java--集合
- 黑马程序员--Java集合
- Mongodb源码分析--主程序入口main()
- 越狱团队否认收钱并中止与太极合作
- 解决 FtpClient 类无法导入 .
- Mongodb源码分析--日志及持久化
- 【Java算法学习】鸡兔同笼问题
- 黑马程序员----java集合
- junit测试工具学习笔记1
- 程序中实现可从两个入口进入类似switch的方法
- ZOJ 1151 Word Reversal
- 【*_*】【opencv】CvvImage 的问题
- 程序员:如何写出杀手级简历
- 一个经典例子让你彻彻底底理解java回调机制(一)
- 新加坡架构师面试总结
- Objective-C对象模型及应用