java数据结构-集合与映射
接口 | 子接口 | 是否有序 | 是否允许元素重复 |
---|---|---|---|
Collection | 否 | ||
List | ArrayList | 否 | 是 |
LinkedList | 否 | 是 | |
Vector | 否 | 是 | |
Set | AbstractSet | 否 | 否 |
HashSet | 否 | 否 | |
TreeSet | 是(用二叉排序树) | 否 | |
Map | AbstractMap | 否 | 使用key-value来映射和存储数据,key必须唯一,value可以重复 |
HashMap | 否 | ||
TreeMap | 是(用二叉排序树) | 使用key-value来映射和存储数据,key必须唯一,value可以重复 |
List集合
Arraylist的常用操作
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> mylist = new ArrayList<Integer>();
// 没有添加任何数之前的arralist
System.out.print(mylist.size());
mylist.add(1);
mylist.add(2);
mylist.add(3);
mylist.add(4);
mylist.add(5);
mylist.add(6);
System.out.print(mylist.size());
// 遍历有三种方式
System.out.println();
// 通过索引值进行遍历
for (int i = 0; i < mylist.size(); i++) {
System.out.print(mylist.get(i) + " ");
}
System.out.println();
// 通过for循环进行遍历还记得我们讲过的增强for循环吗
for (Integer num : mylist) {
System.out.print(num + " ");
}
System.out.println();
// 通过迭代器进行遍历
System.out.println("通过迭代器进行遍历");
Iterator<Integer> it = mylist.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
// 下面是怎样将arraylist to array有两种方式
// 第一种是
Integer[] integer1 = new Integer[mylist.size()];
mylist.toArray(integer1);
// 第二种
Integer[] integer2 = mylist.toArray(new Integer[0]);
// 下面是一些常用的操作
mylist.add(6);
mylist.remove(1);// 移除某一个索引处的一个东西
mylist.remove((Object) 3);// 移除某一个对象
System.out.println("是否包含5" + mylist.contains(5));// 判断是否包含5
mylist.clear();// 清空
System.out.println("是否为空" + mylist.isEmpty());// 判断是否包含5
}
}
for循环删除元素注意的问题
删除该集合中所有字符串为b的数据
ArrayList的底层结构是数组类型,数组这种数据结构的特点是删除其中某个元素时,后面的所有元素索引都会前移,此时for循环的指针却会下移,因此会略过下一个元素
解决方案是删除时将指针回调一次:
for (int i = 0; i < list.size(); i++) {
if("b".equals(list.get(i))) {
list.remove(i);
i--;
}
}
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("b");
list.add("e");
list.add("b");
list.add("c");
Iterator it=list.iterator();
while(it.hasNext()) {
if("b".equals(it.next())) {
// 使用迭代器中的remove()方法,可以删除元素.
it.remove();
}
}
System.out.println(list.toString());
}
java8的流删除集合中的元素
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Demo {
public static void main(String[] args) {
List<String> strList2 = new ArrayList<>();
strList2.add("a");
strList2.add("ab");
strList2.add("ac");
strList2.add("ad");
strList2.forEach(System.out::print);
System.out.println();
strList2.removeIf(s -> s.equals("a"));
strList2.forEach(System.out::print);
System.out.println();
strList2 = strList2.stream().filter( s -> !s.equals("ac")).collect(Collectors.toList());
strList2.forEach(System.out::print);
System.out.println();
//让strList2中只保留strList中也有数据,等于取两个集合的交集。
List<String> strList = Arrays.asList("a", "b", "aa", "ab", "ba");
strList2.retainAll(strList);
strList2.forEach(System.out::print);
}
}
LinkedList的常用操作
集合的拷贝
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class LinkedListTest {
public static void main(String[] args) {
LinkedList<String> lList = new LinkedList<String>();
lList.add("1");
lList.add("2");
lList.add("3");
lList.add("4");
lList.add("5");
//深拷贝
List<String> dic = new ArrayList<String>(Arrays.asList(new String[lList.size()]));
Collections.copy(dic,lList);
List<String> dest1 = new ArrayList<String>();
Collections.addAll(dest1, new String[lList.size()]);
Collections.copy(dest1, lList);
//浅拷贝
List<String> newList = new ArrayList<String>();
newList.addAll(lList);
List<String> newList1 = new ArrayList<String>(lList);
System.out.println("链表的第一个元素是 : " + lList.getFirst());
System.out.println("链表最后一个元素是 : " + lList.getLast());
lList.removeFirst();
lList.removeLast();
System.out.println(lList.toString());
System.out.println(dic.toString());
System.out.println(dest1.toString());
System.out.println(newList.toString());
System.out.println(newList1.toString());
//根据范围删除列表元素
dic.subList(2, 5).clear();
System.out.println(dic.toString());
//查找元素位置
System.out.println(newList.indexOf("2"));
System.out.println(newList.lastIndexOf("2"));
}
}
Set集合
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
——HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
——TreeSet:
有序的存放:TreeSet 线程不安全,可以对Set集合中的元素进行排序
通过compareTo或者compare方法来保证元素的唯一性,元素以二叉树的形式存放。
HashSet的常用操作
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Set<Integer> set = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
for(int i = 0;i<10;i++){
set.add(i);
set2.add(i);
}
//去重,最终只会有一组0-9;
set.addAll(set2);
System.out.println(set.toString());
//containsAll如果集合中的元素与指定集合的元素都相同,则返回true
//contains如果集合中存在指定元素,则返回true,不存在则返回false;
System.out.println(set.contains(4)+" "+set.containsAll(set2));
//remove删除集合中指定的元素,如果该元素在集合中返回true表示删除成功
System.out.println(set.remove((Object)4));
System.out.println(set.toString());
//removeAll删除集合中与指定集合的元素匹配的元素,如果指定集合的元素有一个在被操作的集合中返回true表示删除成功;如果指定集合的元素都不在集合中返回false表示是删除失败
System.out.println(set2.removeAll(set));
System.out.println(set2.toString());
}
}
TreeSet的常用操作
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。
obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是 负数,则表明obj1小于obj2。
如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0
定制排序
自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法。
Treeset中的数据是自动排好序的,不允许放入null值。 HashSet集合元素可以是null,但只能放入一个null
TreeSet不支持快速随机遍历,只能通过迭代器进行遍历!
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet set = new TreeSet();
set.add("aaa");
set.add("aaa");
set.add("bbb");
set.add("eee");
set.add("ddd");
set.add("ccc");
// 顺序遍历TreeSet
ascIteratorThroughIterator(set) ;
// 逆序遍历TreeSet
descIteratorThroughIterator(set);
// 通过for-each遍历TreeSet。不推荐!此方法需要先将Set转换为数组
foreachTreeSet(set);
}
// 顺序遍历TreeSet
public static void ascIteratorThroughIterator(TreeSet set) {
System.out.print("\n ---- Ascend Iterator ----\n");
for(Iterator iter = set.iterator(); iter.hasNext(); ) {
System.out.printf("asc : %s\n", iter.next());
}
}
// 逆序遍历TreeSet
public static void descIteratorThroughIterator(TreeSet set) {
System.out.printf("\n ---- Descend Iterator ----\n");
for(Iterator iter = set.descendingIterator(); iter.hasNext(); )
System.out.printf("desc : %s\n", (String)iter.next());
}
// 通过for-each遍历TreeSet。不推荐!此方法需要先将Set转换为数组
private static void foreachTreeSet(TreeSet set) {
System.out.printf("\n ---- For-each ----\n");
String[] arr = (String[])set.toArray(new String[0]);
for (String str:arr)
System.out.printf("for each : %s\n", str);
}
}
常用API
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
String val;
TreeSet tSet = new TreeSet();
tSet.add("aaa");
tSet.add("aaa");
tSet.add("bbb");
tSet.add("eee");
tSet.add("ddd");
tSet.add("ccc");
// floor(小于、等于)
System.out.printf("floor bbb: %s\n", tSet.floor("bbb"));
// lower(小于)
System.out.printf("lower bbb: %s\n", tSet.lower("bbb"));
// ceiling(大于、等于)
System.out.printf("ceiling bbb: %s\n", tSet.ceiling("bbb"));
System.out.printf("ceiling eee: %s\n", tSet.ceiling("eee"));
// ceiling(大于)
System.out.printf("higher bbb: %s\n", tSet.higher("bbb"));
// subSet()
System.out.printf("subSet(aaa, true, ccc, true): %s\n", tSet.subSet("aaa", true, "ccc", true));
System.out.printf("subSet(aaa, true, ccc, false): %s\n", tSet.subSet("aaa", true, "ccc", false));
System.out.printf("subSet(aaa, false, ccc, true): %s\n", tSet.subSet("aaa", false, "ccc", true));
System.out.printf("subSet(aaa, false, ccc, false): %s\n", tSet.subSet("aaa", false, "ccc", false));
// headSet()
System.out.printf("headSet(ccc, true): %s\n", tSet.headSet("ccc", true));
System.out.printf("headSet(ccc, false): %s\n", tSet.headSet("ccc", false));
// tailSet()
System.out.printf("tailSet(ccc, true): %s\n", tSet.tailSet("ccc", true));
System.out.printf("tailSet(ccc, false): %s\n", tSet.tailSet("ccc", false));
// 删除并返回第一个元素
val = (String)tSet.pollFirst();
System.out.printf("pollFirst=%s, set=%s\n", val, tSet);
// 删除并返回最后一个元素
val = (String)tSet.pollLast();
System.out.printf("pollLast=%s, set=%s\n", val, tSet);
}
}