|-- List(列表):有索引,允许重复元素
|-- Set(集) :没有索引,不允许重复元素
【java.util.List】
ArrayList:底层数据结构是数组,数组的物理地址是连续的,可以通过位置快速定位到具体元素的地址,所以改查效率高
但是如果是增加和删除元素时,可能会涉及到新建数组,复制元素,移动元素等操作,比较耗时,所以增删效率低LinkedList:底层是靠节点相连的双向循环链表,物理地址不连续,
必须依靠头尾节点不断寻址,找到目标位置,而寻址的过程比较耗时,所以改查效率低;
而增删的时候只需要找到目标位置进行断开和连接节点的操作即可,所以增删效率高;
1.ArrayList
import java.util.ArrayList;
import java.util.Iterator;
/**
* ArrayList
* @author yujie
*
*/
public class SN1_ArrayList {
public static void main(String[] args) {
// 1.构造一个初始容量为 10 的空列表——ArrayList
ArrayList<Object> arrayList = new ArrayList<>();
// 2.链表内添加数据(可以是数字、字符串、或者对象)
for (int i = 0; i < 10; i++) {
arrayList.add("小" + i);
}
// 3.显示列表内容
for (int i = 0; i < arrayList.size(); i++) {
System.out.print(arrayList.get(i) + " ");
}
System.out.println();
// 4.删除小3
arrayList.remove(3);
// 5.添加一个 小A 在 小2 后面
arrayList.add(3, "小A");
// 6.修改小A的名字为小B
arrayList.set(3, "小B");
// 7.返回包含此列表中所有元素的数组
Object[] array = arrayList.toArray();
// 8.返回此列表中的元素数
System.out.println("元素数: " + arrayList.size());
// 9.判断链表是否包含 小8
System.out.println(arrayList.contains("小8"));
/**
* 迭代器iterator
*/
Iterator<Object> iterator = arrayList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.print(next+" ");
}
System.out.println();
// 注意:删除链表不能使用普通for循环方法,需要使用迭代器,如下删除小1:
Iterator<Object> it = arrayList.iterator();
while (it.hasNext()) {
Object next = it.next();
if("小1".equals(next)) it.remove();
}
// 显示方法也可以使用如下
for (Object s : arrayList) {
System.out.print(s+" ");
}
}
}
演示:
2.LinkedList
import java.util.LinkedList;
/**
* LinkedList
* @author yujie
*
*/
public class SN2_LinkedList {
public static void main(String[] args) {
// 1.构造一个初始容量为 10 的空列表——ArrayList
LinkedList<Object> linkedList = new LinkedList<>();
// 2.链表内添加数据(可以是数字、字符串、或者对象)
for (int i = 0; i < 10; i++) {
linkedList.add("小" + i);
}
// 3.显示列表内容
for (int i = 0; i < linkedList.size(); i++) {
System.out.print(linkedList.get(i) + " ");
}
System.out.println();
// 4.删除小3
linkedList.remove(3);
// 5.添加一个 小A 在 小2 后面
linkedList.add(3, "小A");
// 6.修改小A的名字为小B
linkedList.set(3, "小B");
// 7.返回包含此列表中所有元素的数组
Object[] array = linkedList.toArray();
// 8.返回此列表中的元素数
System.out.println("元素数: " + linkedList.size());
// 9.获取链表第一个元素和最后一个元素
System.out.println("第一个:" + linkedList.getFirst() + " 最后一个:" + linkedList.getLast());
// 10.判断链表是否包含 小8
System.out.println(linkedList.contains("小8"));
//11.移除并返回此列表的第一个元素。
System.out.println(linkedList.removeFirst());
System.out.println(linkedList.getFirst());
}
}
演示:
3. Collections工具类
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Collections工具类
*
*/
public class SN3_Collections {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add((int)(Math.random()*100));
System.out.print(list.get(i)+" ");
}
//升序排序
Collections.sort(list);
//反转
Collections.reverse(list);
//打乱
Collections.shuffle(list);
//交换
Collections.swap(list, 1, 2);
}
}
Set集合
使用Set集合的主要原因是因为Set集合里面没有重复的元素。
Set集合有三个常见的实现类:HashSet,TreeSet,LinkedHashSet。
简单的说,如果你关注性能,应该使用HashSet;
如果你需要一个有序的Set集合,应该使用TreeSet;
如果你需要一个Set集合保存了原始的元素插入顺序,应该使用LinkedHashSet。
Set接口
Set接口继承Collection接口。Set集合不允许里面存在重复元素,每个元素都必须是唯一的。你只需要往Set集合简单的添加元素,重复元素会被自动移除
HashSet,TreeSet,LinkedHashSet对比
HashSet是基于散列表实现的,元素没有顺序;add、remove、contains方法的时间复杂度为O(1)。(contains为false时,就直接往集合里存)
TreeSet是基于树实现的(红黑树),元素是有序的;add、remove、contains方法的时间复杂度为O(log (n))(contains为false时,插入前需要重新排序)。
因为元素是有序的,它提供了若干个相关方法如first(), last(), headSet(), tailSet()等;
LinkedHashSet介于HashSet和TreeSet之间,是基于哈希表和链表实现的,支持元素的插入顺序;基本方法的时间复杂度为O(1);
TreeSet例子
TreeSet<Integer>tree=newTreeSet<Integer>();
tree.add(12);tree.add(63);tree.add(34);tree.add(45);Iterator<Integer> iterator = tree.iterator();System.out.print("Tree set data: ");while (iterator.hasNext()) { System.out.print(iterator.next() + " ");}
结果:Tree setdata:12 34 45 63
现在,我们换个元素类型,在进行插入,首先定义一个Dog类,如下class Dog {
intsize;
publicDog(int s) {
size=s;
}
public String toString() {
return size+ "";
}
}
public class Q17 {
public static void main(String[] args) {
TreeSet<Dog>dset= newTreeSet<Dog>();
dset.add(newDog(2));
dset.add(newDog(1));
dset.add(newDog(3));
Iterator<Dog>iterator=dset.iterator();
while(iterator.hasNext()){
System.out.print(iterator.next()+"");
}
}
}
报错:Exceptioninthread"main"java.lang.ClassCastException: simplejava.Dog cannotbecasttojava.lang.Comparable
因为TreeSet是有序的,Dog类需要实现java.lang.Comparable接口的compareTo(),如下:
class Dog implements Comparable{
int size;
public Dog(int s) {
size=s;
}
public String toString() {
returnsize+ "";
}
@Override
public int compareTo(Dog o) {
return size - o.size;
}
}
输出:1 2 3
HashSet例子排序
HashSet<Dog> dset = newHashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog>iterator = dset.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
结果:5 3 2 1 4
排序:HashSet排序Set<Object> set = new HashSet<Object>(); set.add("aaa"); set.add("ccc"); set.add("bbb");System.out.println(sortByValue(set));//set转ArrayList,利用sort排序public static Set<Object> sortByValue(Set<Object> set){ List<Object> setList= new ArrayList<Object>(set); Collections.sort(setList,new Comparator<Object>(){ public int compare(Objecto1,Object o2) { return o1.toString().compareTo(o2.toString()); } }); set = new LinkedHashSet<Object>(setList);//这里注意使用LinkedHashSet(TreeSet存还要排序) return set;}
LinkedHashSet例子
LinkedHashSet<Dog>dset = newLinkedHashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog>iterator= dset.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next()+" ");
}
结果:2 1 35 4
性能测试(add方法)
Random r= newRandom();
HashSet<Dog>hashSet = new HashSet<Dog>();
TreeSet<Dog>treeSet = new TreeSet<Dog>();
LinkedHashSet<Dog>linkedSet= new LinkedHashSet<Dog>();
// start time
long startTime = System.nanoTime();
for (inti = 0; i < 1000; i++){
int x =r.nextInt(1000 - 10) + 10;
hashSet.add(new Dog(x));
}
// end time
long endTime = System.nanoTime();
long duration =endTime - startTime;
System.out.println("HashSet:" + duration);
// start time
startTime= System.nanoTime();
for (inti = 0; i < 1000; i++){
int x =r.nextInt(1000 - 10) + 10;
treeSet.add(new Dog(x));
}
// end time
endTime= System.nanoTime();
duration = endTime - startTime;
System.out.println("TreeSet:" + duration);
// start time
startTime= System.nanoTime();
for (inti = 0; i < 1000; i++){
int x =r.nextInt(1000 - 10) + 10;
linkedSet.add(new Dog(x));
}
// end time
endTime= System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedHashSet:" + duration);
结果是:HashSet最好,TreeSet最差
/**一、是迭代遍历:*/Set<String> set = new HashSet<String>();Iterator<String> it = set.iterator();while (it.hasNext()) { String str = it.next(); //it.remove(); System.out.println(str);}/** "只有" 用iterator遍历时才可以进行删除元素*//**二、for循环遍历:*/for (String str : set) { System.out.println(str);}/**优点还体现在泛型 假如 set中存放的是Object*/Set<Object> set = new HashSet<Object>();/**for循环遍历:*/for (Object obj: set) { if(obj instanceof Integer){ int aa= (Integer)obj; }else if(obj instanceof String){ String aa = (String)obj } ........}
如何根据对象的属性,对集合(list / set)中的对象进行排序
通过java.util.Collections的sort方法,有2个参数,第一个参数是list对象,第二个参数是new Comparator<对象类>(){}方法,这个方法实现了compare()方法,具体代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
package
test2;
import
java.util.ArrayList;
import
java.util.Collections;
import
java.util.Comparator;
import
java.util.List;
public
class
ListSort {
public
static
void
main(String[] args) {
List<Person> personList =
new
ArrayList<Person>();
personList.add(
new
Person(
"王五"
,
32
)) ;
personList.add(
new
Person(
"张三"
,
30
)) ;
personList.add(
new
Person(
"赵六"
,
33
)) ;
personList.add(
new
Person(
"李四"
,
31
)) ;
personList.add(
new
Person(
"孙七"
,
33
)) ;
Collections.sort(personList,
new
Comparator<Person>() {
@Override
public
int
compare(Person p1, Person p2) {
if
(p1.age>p2.age){
return
1
;
}
else
if
(p1.age<p2.age){
return
0
;
}
else
{
return
p1.name.compareTo(p2.name) ;
// 调用String中的compareTo()方法
}
}
});
System.out.println(personList);
}
}
class
Person {
public
String name ;
public
int
age ;
public
Person(String name,
int
age){
this
.name = name ;
this
.age = age ;
}
public
String toString(){
return
"姓名:"
+
this
.name +
";年龄:"
+
this
.age ;
}
}
|
代码执行的结果为:
[姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:孙七;年龄:33, 姓名:赵六;年龄:33]
二:针对set
要排序的对象所属的类implements Comparable接口,重写了compareTo()方法,具体代码如下所示:
package test1; import java.util.Set ; import java.util.TreeSet ; public class TreeSetDemo4{ public static void main(String args[]){ Set<Person> allSet = new TreeSet<Person>() ; allSet.add(new Person("赵六",33)) ; allSet.add(new Person("张三",30)) ; allSet.add(new Person("王五",32)) ; allSet.add(new Person("李四",31)) ; allSet.add(new Person("孙七",33)) ; System.out.println(allSet) ; } } class Person implements Comparable<Person>{ private String name ; private int age ; public Person(String name,int age){ this.name = name ; this.age = age ; } public String toString(){ return "姓名:" + this.name + ";年龄:" + this.age ; } public int compareTo(Person per){ if(this.age>per.age){ return 1 ; }else if(this.age<per.age){ return -1 ; }else{ return this.name.compareTo(per.name) ; // 调用String中的compareTo()方法 } } }
代码执行的结果为:
[姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:孙七;年龄:33, 姓名:赵六;年龄:33]