List接口
特点:1. 元素有序,并且可以重复。2. 两个实现类:ArrayList和LinkedList ArrayList:动态数组+各种方法 LinkedList: 双向链表+各种方法 对于随机访问来说, ArrayList要高于LinkedList 。对于频繁的插入和删除来说, LinkedList要高于ArrayList.基于List接口,两个实现类的方法基本一致。
public class ListDemo01 {
public static void main(String[] args) {
//创建一个ArrayList集合对象
List<String> names = new ArrayList<>();
//创建一个LinkedList集合对象
List<String> adds = new LinkedList<>();
/**
* 添加元素:
* boolean add(E e) : 添加元素, 默认添加到集合尾部
* void add(int index, E element): 插入元素,下标范围 [0,size()]
* boolean addAll(Collection c )
* boolean addAll(int index, Collection c)
*/
names.add("michael");
names.add(1,"bob");
System.out.println(names);
//地址集合添加两个元素
adds.add("beijing");
adds.add("shanghai");
//将地址集合添加到名字集合中
// names.addAll(adds);
// System.out.println(names);
//将地址集合添加到names集合中的两个元素中间
names.addAll(1,adds);
System.out.println(names);
/**
* E get(int index): 获取指定索引处的元素
*/
String ele = adds.get(1);
System.out.println("ele:"+ele);
/**
* 查找元素:
* int indexOf(Object obj): 返回指定元素的第一个下标,如果没有返回-1.
* int lastIndexOf(Object obj): 返回指定元素的最后一个下标,如果没有返回-1.
*/
int index = names.indexOf("bob");
System.out.println("index:"+index);
index = names.lastIndexOf("john");
System.out.println("index:"+index);
/**
* boolean remove(Object obj):
* E remove(int index)
*/
boolean f = names.remove("lucy");
System.out.println("f:"+f);
String address = adds.remove(0);
System.out.println("address:"+address);
System.out.println(adds);
/**
* E set(int index,E e): 将指定位置上的元素替换成形参e
*/
System.out.println("显示:"+names);
String add1 = names.set(2, "深圳");
System.out.println("add1:"+add1);
System.out.println("names:"+names); //[michael, beijing, 深圳, bob]
String add2 = names.set(0,names.set(1,"沈阳"));
System.out.println("add2:"+add2);// michael
System.out.println("names:"+names);// [beijing, 沈阳, 深圳, bob]
/**
* List subList(int fromIndex,int endIndex):
* 用于截取子集,包前不包后
*/
List<Integer> nums = new ArrayList<>();
for (int i = 1; i < 11; i++) {
nums.add(i);
}
System.out.println(nums);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
List<Integer> sub = nums.subList(3, 7);
System.out.println(sub);
//对子集里的每一个元素扩大10倍。
for (int i = 0; i < sub.size(); i++) {
//取出元素*10,然后替换掉原有的元素
// int r = nums.get(i)*10;
// nums.set(i,r);
sub.set(i,sub.get(i)*10);
}
System.out.println(sub);
System.out.println(nums);
new LinkedList<>(sub);
}
}
Queue队列
也是Collection接口的子接口,用来描述一种先进先出(First Input First Output)的数据存储结构。可以理解为是一种特殊的线性表,只能从一头进入,另一头出来,对应的方法 - boolean offer(E e): 从队列的尾部进入 - E poll(): 从队列的头部出来 - E peek(): 查看头部的元素
public class QueueDemo01 {
public static void main(String[] args) {
//创建一个名字队列
Queue<String> names = new LinkedList<>();
//调用offer方法,入队
names.offer("michael");
names.offer("张三");
names.offer("李四");
//查看队列的样子
System.out.println(names);
//查看队列的头部对象
String head = names.peek();
System.out.println(head);
//让头部元素出队
while (names.peek() != null) {
//如果想要移除头部元素,最后先查看是否有头部元素,如果有再移除。
String oldHead = names.poll();
System.out.println(oldHead);
System.out.println(names);
}
}
}
Deque接口
双端队列: 即从队列的两头都可以入队和出队。 Deque接口,实现了双端队列的存储结构, 它是Queue的子接口。 对应的实现类,还是LinkedList(); 提供的方法: offerFirst offerLast pollFirst pollLast
public class QueueDemo02 {
public static void main(String[] args) {
//创建一个双端队列
Deque<String> names = new LinkedList<>();
//添加第一个元素
names.offer("小明");
//第二个元素从队列的头部进入
names.offerFirst("小红");
//第三元素从队列的尾部进入 offer() offerLast()
names.offerLast("小芳");
System.out.println(names);
//移除元素
//移除队列的头部 poll() pollFirst()
String head = names.poll();
System.out.println("head:" + head);
//移除队列的尾部
String tail = names.pollLast();
System.out.println("tail:" + tail);
System.out.println(names);
}
}
使用Deque来模拟栈的存储结构:栈: First Input Last Output 简称FILO
public class QueueDemo03 {
public static void main(String[] args) {
//创建一个存储结构
Deque<String> stack = new LinkedList<>();
//从栈的出口进入, 对应的方法push, 表示将元素推进去
stack.push("michael"); //推入到栈的底部
stack.push("lucy"); //推入,在最底层的上一层
stack.push("lily");
stack.push("tom");
System.out.println(stack);
//出栈(弹出): 对应的方法pop() 将元素弹出栈结构
while (stack.size() > 0) {
String el = stack.pop();
System.out.println(el);
}
}
}
Set接口
是Collection的子接口。
设计初衷:用来存储不重复的元素,元素的顺序是无序的(取出的顺序和存入的顺序无关) (一旦存入,在存储结构里的顺序就固定了。和存入的先后顺序无关) set接口里的方法都是Collection接口的方法HashSet: 是实现了Set接口的最最经典的子类型 底层的存储方式使用的是Hash算法(哈希表)
public class SetDemo01 {
public static void main(String[] args) {
//创建一个Set接口的对象
Set<String> names = new HashSet<>();
//存入michael, lucy, john, tom
names.add("michael");
names.add("lucy");
names.add("john");
names.add("tom");
System.out.println("names: " + names);
System.out.println("names: " + names);
/**
* 打印一下四个元素的hash值
*/
System.out.println("micheal".hashCode()%16);
System.out.println("tom".hashCode()%16);
System.out.println("john".hashCode()%16);
System.out.println("lucy".hashCode()%16);
// `%16` 用于将 hash 值除以 16,并取余数。
names.add("michael");
System.out.println(names);
System.out.println(names.size());
}
}
添加元素 michael, 因为数据结构中已经存在michael,所以新的michal是添加不进来的。 去重原理: 先计算要添加的元素的hash值,然后确定哈希表中该值的位置上是否存在元素 如果不存在,可以添加,如果存在,就需要调用equals进行比较 如果equals返回true,说明不能再存入了。 如果equals返回false,说明可以存入。 注意:每个hash值对应的位置都维护了一个单向链表。可以进行存储hash值相同 equals不同的元素。
LinkedHashSet
是 HashSet 的子类 - LinkedHashSet 集合根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。 - LinkedHashSet 性能插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。 - LinkedHashSet 不允许集合元素重复
public class SetDemo03 {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("bob");
set.add("c"); //重复的,不能添加成功
System.out.println(set);
//使用迭代器遍历
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
TreeSet
1. TreeSet 是SortedSet接口的实现类。 2. TreeSet集合的元素是有序的,即内部维护一个二叉树算法的排序方式 3. TreeSet集合里的元素也不能重复 4. TreeSet默认排序是升序方式,如果想要改变默认的排序方式,可以自定义一个比较器,传入构造器中 回顾: LinkedHashSet,使用链表维护向集合中插入元素时的顺序
public class SetDemo04 {
public static void main(String[] args) {
Set<String> set = new TreeSet<>();
set.add("a");
set.add("h");
set.add("b");
set.add("f");
set.add("d");
set.add("bob");
set.add("bab");
System.out.println(set);
Comparator c1 = new Comparator<Integer>(){
public int compare(Integer o1 ,Integer o2){
return o2-o1;
}
};
Set<Integer> nums = new TreeSet<>(c1);
nums.add(10);
nums.add(1);
nums.add(20);
nums.add(2);
System.out.println(nums);
}
}
Sort排序 1. 不管是在数组中,还是在集合中。 要求元素必须是Comparable的子类型,因此底层需要调用Comparable的 compareTo方法。 所以,自定义的类,如果想要排序,那么必须实现Comparable接口,以及重写 compareTo方法 2. 在上述的基础之上,如果想要重新指定排序方式,不应该修改compareTo方法里的逻辑 而是应该使用Comparator比较器接口,来定义一个新的比较规则。调用集合或者数组的 相关重载方法,可以传入一个比较器的这样的方法,进行新的排序。
集合工具类:Collections 。数组工具类:Arrays 1. 集合工具类和数组工具类一样,都提供了很多常用的方法,来操作集合对象。 - void sort(List<E> list) : 对集合元素进行升序排序。 - void sort(List<E> list,Comparator<E> c): 可以使用比较器来重新定义比较规则
public class SortDemo02 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add((int)(Math.random() * 100));
}
System.out.println(list);
Collections.sort(list);
System.out.println(list);
Compartor c1 = new Comparator<Integer>(){
public int compare(Integer o1,Integer o2){
return o2-o1;
};
Collections.sort(list,c1);
System.out.println(list);`
}
集合工具类其他方法演示:
public class CollectionsDemo {
public static void main(String[] args) {
List<String> names = new LinkedList<>();
names.add("michael");
names.add("peter");
names.add("mark");
names.add("john");
names.add("jane");
//打印集合: 顺序为添加时的顺序
System.out.println(names);
//1. 调用集合工具类里的反转方法,将集合元素颠倒过来
Collections.reverse(names);
System.out.println("反转后的结果:"+ names);
//2. 调用工具类里的洗牌(打乱)方法
Collections.shuffle(names);
System.out.println("打乱后的结果:"+names);
//3. 将第二个和倒数第二个做一下交换
Collection.swap(name,1,names.size()-2);
System.out.println("交换后的结果:"+names);
//4. 调用max方法: 底层使用的自然排序,找到最大的
String ele = Collection.max(names);
System.out.println(ele);
//5. 调用min方法: 底层使用的自然排序,找到最小的
String ele2 = Collections.min(names);
System.out.println(ele2);
names.add("michael");
names.add("michael");
names.add("michael");
System.out.println("集合:"+names);
System.out.println("集合长度:"+names.size());
//8.调用工具类方法找出michael出现的次数
int count = Collections.frequency(names, "michael");
System.out.println("michael出现的次数:"+count);
//9. 将集合里的所有michael替换成张三
Collections.replaceAll(names,"michael","张三");
System.out.println("替换后的样子:"+names);
}
}
将集合转成Object[] 数组,想使用自己的方法属性有需要强转。
public class CollectionDemo02 {
public static void main(String[] args) {
List<String> names = new Arrays<>();
names.add("michael");
names.add("peter");
names.add("mark");
Object[] arr1 = names.toArray();
Object obj = arr1[1];\
if(obj instanceof String){
String str = (String) obj;
char ch = str.charAt(1);
System.out.println(ch);
}
String[] arr = new String[0];
String[] arr2 = names.toArray(arr);
System.out.println(Arrays.toString(arr2));
if(arr2[0].endsWith("el")){
System.out.println("是");
}else {
System.out.println("不是");
}
arr2[0] = "lucy";
}
}
数组转成的集合能改长度。 放入一个新集合,对新集合进行操作
public class CollectionsDemo03 {
public static void main(String[] args) {
String[] names = new String[5];
names[0] = "michael";
names[1] = "tom";
names[2] = "lucy";
names[3] = "lily";
names[4] = "John";
List<String> list = Arrays.asList(names);
System.out.println(list);
List<String> arr2 = new ArrayList<>(list);
arr2.add("张三");
arr2.add("李四");
System.out.println(arr2);
int index = arr2.indexOf("张三");
Collections.swap(arr2,5,0);
System.out.println(arr2);
}
}