这个小结是对集合方法总结一下,源码,底层原理参考java3y的集合总结那篇
集合概述
集合就是用来集中存储对象的,相当于一个容器,并且给了一些操作集合中对象的基本增删改查等方法,方便我们使用,它不能存储基本数据类型,只能存储引用类型,存入的int ,char等基本类型都经过了自动装箱。虽然数组也可以存储对象,但数组大小是固定的,不方便进行对象的增删改查。
基本框架
基本方法
Collection接口定义的方法
public class Main {
public static void main(String[] args) {
Collection list=new LinkedList<>();//这里体现了java的引用多态,Collection父接口(接口是特殊的类)的引用指向子类的对象,这样的话,调用方法时,不能调用子类特有的方法,只能调用子类重写或者继承的方法
list.add("北京");
list.add("上海");
list.add("重庆");
list.add("天津");
list.remove("北京");//删除元素// list.clear();//删除所有元素// list.removeAll(list);//删除list中所有元素
System.out.println(list.contains("北京"));//是否包含元素
System.out.println(list.size());//元素个数for (String string : list) {
System.out.println(string);
}
Object[] a=list.toArray();//将集合转换为Object数组
System.out.println(a[1]);
String[] b=list.toArray(new String[0]);//因为集合中只有String类型元素,所以可转换为String数组
System.out.println(b[1]);// Collection list1=new LinkedList<>(list);//含参构造方法,初始化后不为空,存储的是list的元素//使用迭代器遍历集合中的对象
Iterator iterable = list.iterator();while(iterable.hasNext()) {//iterable.hasNext()方法返回迭代器中是否还有对象
System.out.println(iterable.next());//iterable.next()方法返回迭代器中的元素
}
}
}
迭代器(Iterable)Collection接口继承了Iterable接口,迭代就是从容器的当前元素获取其后续元素进行访问的过程,也叫遍历。所以迭代器是一个可以遍历集合中每个元素的对象。调用集合对象的iterable()方法就可以得到Iterable对象,再调用Iterable对象的方法就可以遍历集合中元素。他定义了三个方法:`hasnext() next() remove()`,具体使用看上面代码。在遍历元素中除了使用迭代器,还可以使用简单的for循环和foreach()方法
List常用方法
List接口是Collection的子接口,,它是一种包含有序元素的线性表。List中的元素的顺序关系由添加进来的顺序决定,可以通过下标来访问元素,范围是0~size-1,List接口的实现类有ArrayList,LinkedList,Vector和Stack.List接口除了继承Collection的方法外,还定义了自己的方法。使之能够在具体位置添加删除元素。
List接口
public class Main {
public static void main(String[] args) {
List list=new LinkedList<>();
list.add("北京");
list.add("上海");
list.add("重庆");
list.add("天津");// list.remove("北京");//删除元素// list.clear();//删除所有元素// list.removeAll(list);//删除list中所有元素// System.out.println(list.contains("北京"));//是否包含元素// System.out.println(list.size());//元素个数// for (String string : list) {// System.out.println(string);// }// Object[] a=list.toArray();//将集合转换为Object数组// System.out.println(a[1]);// String[] b=list.toArray(new String[0]);//因为集合中只有String类型元素,所以可转换为String数组// System.out.println(b[1]); Collection list1=new LinkedList<>(list);//含参构造方法,初始化后不为空,存储的是list的元素// //使用迭代器遍历集合中的对象// Iterator iterable = list.iterator();// while(iterable.hasNext()) {//iterable.hasNext()方法返回迭代器中是否还有对象// System.out.println(iterable.next());//iterable.next()方法返回迭代器中的元素// }// List特有的方法,上面是继承的Collection的方法
list.add(4, "哈尔滨");//在指定位置插入元素
list.remove(4);//移除指定位置元素
System.out.println(list.get(0));//得到指定位置元素//修改指定位置元素,返回被修改的元素
System.out.println(list.set(1, "福建"));//上海
list.indexOf("重庆");//返回元素首次出现的位置
list.lastIndexOf("天津");//返回元素最后出现的位置
List list1=new LinkedList<>(list);//含参构造方法,初始化后不为空,存储的是list的元素
list1.addAll(2, list);//在指定位置插入集合全部元素
}
}
双向迭代器
list提供了listIterable()
方法返回ListIterable
对象。它可以从前后两个方向遍历线性表中元素,在迭代器中修改元素以及获得元素的当前位置,ListIterable
是Iterable
的子接口,不但继承了Iterable接口中的方法,还定义了自己的方法。
ArrayList类
继承了List接口。底层是数组,插入删除时要移动其他元素,,当很多元素进行插入删除时,操作速度较慢。添加元素时容量会自动增大,但不能自动缩小,要使其缩小为当前列表的容量使用
trimToSize()
方法ArrayList中特有的常用方法不多,比如
trimToSize()
List list=new ArrayList<>();//构造方法,初始容量10
List list2=new ArrayList<>(100);//自定义初始容量
List list1=new ArrayList<>(list);//含参构造方法,创建包含list中所有元素的数组列表
list.add("北京");
list.add("上海");
list.add("重庆");
list.add("天津");
LinkedList类
*继承了List接口。底层是链表,可以在任意位置插入删除元素而不需要移动其他元素。大小可以动态增加或减少。
public class Main {
public static void main(String[] args) {
LinkedList list=new LinkedList<>();//构造方法,初始容量10
LinkedList list1=new LinkedList<>(list);//创建包含容器list中所有元素的链表
list.add("北京");
list.add("上海");
list.add("重庆");
list.add("天津");// list.remove("北京");//删除元素// list.clear();//删除所有元素// list.removeAll(list);//删除list中所有元素// System.out.println(list.contains("北京"));//是否包含元素// System.out.println(list.size());//元素个数// for (String string : list) {// System.out.println(string);// }// Object[] a=list.toArray();//将集合转换为Object数组// System.out.println(a[1]);// String[] b=list.toArray(new String[0]);//因为集合中只有String类型元素,所以可转换为String数组// System.out.println(b[1]); Collection list1=new LinkedList<>(list);//含参构造方法,初始化后不为空,存储的是list的元素// //使用迭代器遍历集合中的对象// Iterator iterable = list.iterator();// while(iterable.hasNext()) {//iterable.hasNext()方法返回迭代器中是否还有对象// System.out.println(iterable.next());//iterable.next()方法返回迭代器中的元素// }// List特有的方法,上面是继承的Collection的方法// list.add(4, "哈尔滨");//在指定位置插入元素// list.remove(4);//移除指定位置元素// System.out.println(list.get(0));//得到指定位置元素// //修改指定位置元素,返回被修改的元素// System.out.println(list.set(1, "福建"));//上海// list.indexOf("重庆");//返回元素首次出现的位置// list.lastIndexOf("天津");//返回元素最后出现的位置// List list1=new LinkedList<>(list);//含参构造方法,初始化后不为空,存储的是list的元素// list1.addAll(2, list);//在指定位置插入集合全部元素// LinkedList特有方法
list.addFirst("湖南");//将元素插入开头
list.addLast("南京");//将元素插入末尾
list.getFirst();//返回第一个元素
list.getLast();//返回最后一个元素
list.removeFirst();//删除并返回第一个元素
list.removeLast();//删除并返回最后一个元素
}
}
Set常用方法
Set接口是Collection的子接口。Set中不含重复元素,Set接口没有定义新的方法,只是继承了Collection接口的方法。Set集合中元素没有特定顺序,与元素加入时顺序无关,而且加入的对象一定不能重复。它的常用实现类有
HashSet
类,TreeSet
类和LinkedHashSet
类
HashSet类
*继承Set接口。它的底层是哈希表,一个元素为链表的数组。HashSet集合对包含元素的访问不是像线性表一样使用下标,而是根据哈希码来存取集合中的元素,并且里面的元素不能重复,输出也没有顺序。
public static void main(String[] args) {
HashSet hs=new HashSet<>();
hs.add("北京");
hs.add("上海");
hs.add("重庆");
hs.add("天津");// hs.add("北京");集合中包含北京,会返回false,
hs.clear();//删除所有元素
hs.contains("北京");//是否包含元素
hs.size();//集合中元素个数
}
LinkedHashSet类
LinkedHashSet
类是HashSet
的子类,底层是哈希表和链表。与HashSet
不同的是它对所有的元素维护一个双向链表,该链表定义了元素的迭代顺序,这个顺序是元素插入时的顺序。
TreeSet类
TreeSet
类继承了Set
接口和SortedSet
接口。它的底层是红黑树。与HashSet
不同的是它的元素总是处于有序状态,所以当排序重要时使用TreeSet
,否则使用HashSet
。添加到TreeSet
中的元素必须是可以比较的,所以元素的类必须实现Comparable
接口。实现
Comparable
接口的类
TreeSet hs=new TreeSet<>();//自然顺序排序
hs.add("one");
hs.add("two");
hs.add("three");
hs.add("four");//在集合中顺序是four one three two 字母顺序// hs.add("one");集合中包含北京,会返回false,
hs.first();//返回集合中第一个元素
hs.last();//返回集合中最后一个元素
hs.subSet("one", "two");//返回有序集合中子集合,范围是[one,two)
System.out.println( hs.subSet("one", "two"));//[one, three]for (String string : hs) {
System.out.print(string+" ");//four one three two
}
Set hs1=new TreeSet<>(new comparator());//给定的比较器c排序
hs1.add("one");
hs1.add("two");
hs1.add("three");
hs1.add("four");for (String string : hs1) {
System.out.println(string);//two three one four
}
}
}class comparator implements Comparator<String>{@Overridepublic int compare(String o1, String o2) {// TODO 自动生成的方法存根return o2.compareTo(o1);
}
}
Queue常用方法
Queue
接口是Collection
的子接口,以先进先出的方式排列元素,一般称为队列。它有两个子接口,Deque
和PriorityQueue
,Deque
实现双端队列,PriorityQueue
实现一种优先队列,优先队列的顺序是根据元素的值排列的。Deque
接口被ArrayDeque
和LinkedList
所继承。Queue
接口除了继承Collection
的方法外,还自定义了一些自己特有的方法。
Queue
Queue qu=new ArrayDeque<>();
qu.add("11111");//插入到队列中
qu.add("22222");
qu.add("33333");
qu.add("44444");// 这三种方法当队列容量异常和队列为空时抛出异常,如IllegalStateException,NoSuchElementException异常// qu.add("55555");// qu.element();//返回队列头元素,但不将其删除 // qu.remove();//返回队列头元素,并将其删除 // 这三种方法插入失败或者队列为空时返回false// qu.offer("66666");//将指定的元素插入到队列中// qu.poll();//返回队列头元素,并将其删除 // qu.peek();//返回对列头元素,但不删除
Deque
Deque
接口实现双端队列,支持两端插入和删除元素,同时实现了Stack和Queue的功能。除了继承Queue
的方法,自己也有一些特有的方法。
Deque qu1=new ArrayDeque<>();// 队首元素操作
qu1.addFirst("11111");//插入
qu1.offerFirst("11111");
qu1.removeFirst();//返回并删除
qu1.pollFirst();
qu1.getFirst();//返回不删除
qu1.peekFirst();// 队尾元素操作
qu1.addLast("11111");//插入
qu1.offerLast("11111");
qu1.removeLast();//返回并删除
qu1.pollLast();
qu1.getLast();//返回不删除
qu1.peekLast();
qu1.removeFirstOccurrence("111111");//删除第一次出现的元素
qu1.removeLastOccurrence("111111");//删除最后一次出现的元素
ArrayDeque类和LinkedList类
ArrayDeque
和LinkedList
继承了Queue
和Deque
的方法。ArrayDeque
底层是数组,LinkedList
底层是链表。后者比前者使用起来更加灵活继承了
Collection
接口,所以可以用迭代器来遍历,当然也可以用foreach()
List,Set和Queue之间的转换
因为List,Set和Queue接口的实现类的构造方法都可以接收一个Collection对象来初始化,所以可以借此来完成List,Set和Queue之间的转换。
//构造方法
public ArrayList(Collection c)public HashSet(Collection c)public LinkedList(Collection c)
Queue qu=new LinkedList<>();
qu.add("11111111");
qu.add("22222222");
List mylist=new ArrayList<>(queue);
Set set=new HashSet<>(mylist);
Map接口常用方法
Map接口
Map
接口是用来存储“键值对”的。Map中的元素都是成对出现的,他提供了键到值的映射。在Map
中存储的关键字和值都必须是对象,并要求关键字是唯一的,而值可以重复。在检索元素时,可以通过对键的访问来找到对应的值。Map
接口常用的实现类有HashMap
,TreeMap
,Hashtable
和LinkedHashMap
.
public class map {
public static void main(String[] args) {
Map m=new HashMap();
m.put("1111", "成都");
m.put("2222", "上海");
m.put("3333", "福建");
m.put("4444", "湖南");
m.put("5555", "太原");
m.get("111");//返回指定键的值
m.remove("2222");//删除指定键的键值对
m.containsKey("1111");//返回是否包含指定的键
m.containsValue("成都");//返回是否包含指定的值
m.replace("3333", "河北");//替换指定的值
m.size();//键值对个数
m.isEmpty();//是否为空// m.clear();//删除所有键值对// m.values();//返回由值组成的Collection对象// m.keySet();//返回由键组成的Set对象// n.entrySet();//返回键值对组成的Set对象// System.out.println(m.values());//[成都, 河北, 湖南, 太原]//在键和值上进行迭代//foreach()方法for (String key : m.keySet()) {
System.out.print(key+" ");//1111 3333 4444 5555
}
System.out.println();//迭代器
Iterator iterable = m.keySet().iterator();while(iterable.hasNext()) {//iterable.hasNext()方法返回迭代器中是否还有对象
System.out.print(iterable.next()+" ");//1111 3333 4444 5555
}
System.out.println();for(Entry entry: m.entrySet()) {// System.out.print(entry+" ");//1111=成都 3333=河北 4444=湖南 5555=太原
String k=entry.getKey();
String v=entry.getValue();
System.out.print(k +" "+ v+" ");//1111 成都 3333 河北 4444 湖南 5555 太原
}
}
}
迭代器
在Map
上可以使用foreach
也可以使用迭代器,关于键的实现看上面代码,而键,值,键值对的区别在于键使用m.keySet()
值使用m.values()
键值对使用m.entrySet()
HashMap类
HashMap
底层是哈希表,它继承了Map
接口,删除添加效率较高,但元素无序。它的方法大都继承Map
,所以下面方法介绍不写了。
TreeMap
TreeMap
类继承了Map
接口和SortMap
接口,所以它的元素是有序的,因此也可以像TreeSet
一样自定义排序。也存在一些特有的方法*
public class map {
public static void main(String[] args) {
// Map m=new HashMap();
Map n=new TreeMap();// Map n=new TreeMap(Comparator c);//c为自定义比较器// m.put("1111", "成都");// m.put("2222", "上海");// m.put("3333", "福建");// m.put("4444", "湖南");// m.put("5555", "太原");// m.get("111");//返回指定键的值// m.remove("2222");//删除指定键的键值对// m.containsKey("1111");//返回是否包含指定的键// m.containsValue("成都");//返回是否包含指定的值// m.replace("3333", "河北");//替换指定的值// m.size();//键值对个数// m.isEmpty();//是否为空// m.clear();//删除所有键值对// m.values();//返回由值组成的Collection对象// m.keySet();//返回由键组成的Set对象// n.entrySet();//返回键值对组成的Set对象// System.out.println(m.values());//[成都, 河北, 湖南, 太原]//在键和值上进行迭代//foreach()方法// for (String key : m.keySet()) {// System.out.print(key+" ");//1111 3333 4444 5555 // }// System.out.println();// //迭代器// Iterator iterable = m.keySet().iterator();// while(iterable.hasNext()) {//iterable.hasNext()方法返回迭代器中是否还有对象// System.out.print(iterable.next()+" ");//1111 3333 4444 5555 // }// System.out.println();// for(Entry entry: m.entrySet()) { System.out.print(entry+" ");//1111=成都 3333=河北 4444=湖南 5555=太原 // String k=entry.getKey();// String v=entry.getValue();// System.out.print(k +" "+ v+" ");//1111 成都 3333 河北 4444 湖南 5555 太原 // }
n.put("7777", "aaa");
n.put("2222", "bbb");
n.put("3333", "ccc");
n.put("4444", "ddd");
n.put("5555", "eee");
System.out.println(n);//{2222=bbb, 3333=ccc, 4444=ddd, 5555=eee, 7777=aaa}//键值对是按照键的顺序存放进去的,键的顺序是字母顺序
n.firstKey();//返回第一个键
n.lastKey();//返回最后一个键
n.firstEntry();//返回第一个键值对
n.lowerKey("3333");//返回小于给定键的最大值
n.floorKey("3333");//返回小于等于给定键的最大值
n.higherKey("3333");//返回大于给定键的最小值
n.ceilingKey("3333");//返回大于等于给定键的最小值
}
}