Java集合
Collection接口
Collection接口是List,Set,Queue接口的父类,因此该接口定义的方法能够用于操作List,Set,Queue集合。
看看List的接口:
@Override
public boolean add(Object o) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection c) {
return false;
}
@Override
public boolean addAll(Collection c) {
return false;
}
@Override
public boolean addAll(int index, Collection c) {
return false;
}
@Override
public boolean removeAll(Collection c) {
return false;
}
@Override
public boolean retainAll(Collection c) {
return false;
}
@Override
public void clear() {
}
@Override
public Object get(int index) {
return null;
}
@Override
public Object set(int index, Object element) {
return null;
}
@Override
public void add(int index, Object element) {
}
@Override
public Object remove(int index) {
return null;
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@Override
public ListIterator listIterator() {
return null;
}
@Override
public ListIterator listIterator(int index) {
return null;
}
@Override
public List subList(int fromIndex, int toIndex) {
return null;
}
使用Lambda表达式遍历集合
因为Java8的Iterable接口增加了forEach(Consumer action)默认方法。
而Iterable接口是Collection接口的父类,因此能够使用Lambda表达式。
Consumer接口为函数式接口,唯一一个方法accept。
程序会将集合的元素依次传递给Consumer的accept方法,所以Lambda表达式实现是accept方法。
使用Java8增强的Iterator遍历集合元素
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
void forEachRemaining(Consumer<? super E> action) ;
}
remove();删除集合it.next()返回的元素。利用迭代器对集合元素其他操作(赋值)不能够改变集合的元素值。
it.forEachRemaining(obj->System.out.println("迭代集合元素:"+obj));
使用foreach循环遍历集合元素
for(Object obj:books){//不能修改集合元素
}
使用Java8增强的Predicate操作集合
Collection集合新增的方法,removeIf(Predicate filter)
使用Lambda表达式(目标类型是Predicate )过滤集合
books.removeIf(ele->((String)ele).length()<10);
使用Java8增强的Stream操作集合
Java8的流式的API,Stream,IntStream,LongStream,DoubleStream,Stream是一个通用的接口.
如何使用Stream?
1使用Stream,IntStream,LongStream,DoubleStream的builder()类方法创建该Stream对应的Builder.
2重复调用Builder的add方法添加多个元素。
3调用Builder的build方法获得对应的Stream。
4调用Stream的聚集方法。
Collection接口的stream方法,支持流操作。
Stream接口中的中间方法:返回值是另一个流。
Stream接口中的末端方法:流被销毁。
Set集合
HashSet类:
不能保证元素有序,不是同步的,多线程操作同一个HashSet,必须使用代码保证其同步。集合元素的值可以是null。
HashSet集合判断两个元素相同的标准是:通过equals比较放回true,而且两个对象的hashCode值也相同。
把一个对象放入HashSet集合中,如果重新写equals方法,就必须重写hashCode方法。这是因为equals方法返回true,如果hashCode值不同,从而使两个具有相同的元素的两个对象添加成功。这就违背了set集合元素唯一的规则。
如果hashCode相同,而equals返回false,这就更麻烦。HashSet集合会试图根据hash表保存在同一个位置,但是又不行,否则会只剩下一个对象,所以采用了链式存储结构。访问元素的时候也是根据hashCode值快速定位槽位slot,所以具有两个以上的相同hashCode值元素,会导致性能的下降。
LinkedHashSet类:
有序的链式存储,保证元素与添加时候一致,性能低于HashSet。
TreeSet类
TreeSet是SortedSet接口的实现类,保证了集合元素的有序状态。
总之一句话:如果试图把一个对象添加到TreeSet集合中,而且必须是同一种类型的数据,必须实现Comparable接口,否则将抛出异常。
TreeSet集合判断两个对象相等的标准:两个对象通过CompareTo比较是否返回0,不为0就不相等,才能添加集合中。
定制排序:new TreeSet(Comparator c)
HashSet和TreeSet:
添加、查询时用HashSet,效率高。只有保证排序状态的Set,用TreeSet,它会用了红黑树算法维护集合元素的次序。LinkedHashSet遍历元素的时候要更快。
List集合
ListIterator增加了迭代中添加元素的功能,也继承了Iterator删除元素的功能,此外增加了向前遍历的功能。
ArrayList和Vector实现类
创建一个空的集合默认大小为10.ArrayList是线程不安全的,操作是需要手动同步。而Vector是线程安全的。
Stack是Vector的子类,是栈结构的,同样是线程安全的、性能较差的。可以考虑使用ArrayDeque使用栈功能。
Arrays.ArrayList是Arrays内部类的实例,不是ArrayList和Vector实例。不能使用ArrayList和Vector的方法操作。
Queue集合
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
PriorityQueue实现类
不允许插入null元素,按照元素的大小重新排列,不是按照元素的添加顺序存储,是一个比较标准的队列。
Deque接口和ArrayDeque实现类:同时具备栈和队列的功能
public interface Deque<E> extends Queue<E> {
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e);
boolean offerLast(E e);
E removeFirst();
E removeLast();
E pollFirst();
E pollLast();
E getFirst();
E getLast();
E peekFirst();
E peekLast();
boolean removeFirstOccurrence(Object o);
boolean removeLastOccurrence(Object o);
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
void push(E e);
boolean remove(Object o);
boolean contains(Object o);
public int size();
Iterator<E> descendingIterator();
}
LinkedList实现类:实现了List<E>, Deque<E>, 具备List、栈和队列的功能
遍历List集合,对于ArrayList和Vector使用get方法,对于LinkedArrayList使用迭代器。
经常插入、删除的包含大量数据的List,使用LinkedArrayList。
Map集合
HashMap和HashTable都是Map接口的实现类。
Java8改进了HashMap的实现,存在key冲突的情况下依然具有很好的性能。两者之间存着两点典型的区别。HashTable是线程安全的,HashMap不是线程安全的,所以性能会高些。HashTable不允许使用null作为key或者value,而HashMap可以使用null作为key或者value。
由于HashMap的key不能重复,所以最多只有一个key-value对的key为null,但是可以有很多为null的value。
HashMap和HashTable判断key相同的标准:equals返回true,且两个key的hashCode值相同。
HashMap和HashTable判断value相同的标准:equals返回true。
LinkedHashMap实现类,具有顺序性。
Properties类是HashTable的子类。
public String getProperty(String key)
public String getProperty(String key, String defaultValue)
public synchronized Object setProperty(String key, String value)
public synchronized void load(Reader reader) throws IOException {
load0(new LineReader(reader));
}
public void store(Writer writer, String comments)
SortedMap接口和TreeMap实现类
TreeMap也有两种排序方式:自然排序和定制排序。
IdentityHashMap实现类:
保证key严格的相等。例如字符串常量。
操作集合的工具类Collections
Java提供了一个操作Set,List和Map等集合的工具类Collections。反转List集合的元素,随机排序(洗牌)、向前移动或者向后移动指定数量的元素,二分查找,指定集合中指定元素出现的次数,使用新值代替旧值,子List对象在父List对象第一次出现的位置,根据自然排序或者定制排序返回最大值或者最小值,将指定集合包装成线程同步的集合。