欢迎光临
一起学习,一起进步

数据结构:JAVA中的List

什么是List?

Java的List是一个接口,继承自Collections接口,不能直接进行对象的创建,(List包括什么?)它的具体实现类常见的有ArrayList和LinkedList,分别是数组和链表这两种数据结构的实现,这的链表是一个双向链表,LinkIterator可以进行双向遍历。我们可以方便的将任何数据类型(类的对象)放在List这样的容器里面,当然,需要保证所有的数据都具有同样的数据类型或者是同一个类的对象。(各自在用法和存储上有什么区别?)对于ArrayList和LinkedList的使用区别主要体现在数组和链表的数据结构用法区别上,前者在内存中是连续存储的,所以随机访问速度很快,遍历和查找会比较方便;而后者是一个接一个连起来的,在内存中的分布是非连续的,由于链表的特殊结构,它对链表中间的数据进行修改,插入和删除等操作都很快,也比较方便。当然这里指的是中间的数据,如果我们需要对List的尾元素进行频繁删除和插入操作,还是ArrayList的效率比较高的。两种List对于内存的扩展方式也是不同的,ArrayList可以进行初始化Capacity的配置,在之后如果数据长度超过了当前的capacity,ArrayList会再分配当前的capacity/2的容量,以此类推;当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。当然,ArrayList也是可以自定义如何进行内存的扩展的(方法改为了private,现在不行了),由于内存扩展时需要进行复制操作,所以使用的时候如果知道预期的List大小最好自己先指定。LinkedList在内存中是分散的,所以添加元素的时候跟capacity没什么关系。

Java中对List集合的常用操作

1.list中添加,获取,删除元素;
添加方法是:.add(e);  获取方法是:.get(index);  删除方法是:.remove(index); 按照索引删除;  .remove(Object o); 按照元素内容删除;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<String> person=new ArrayList<>();
            person.add("jackie");   //索引为0  //.add(e)
            person.add("peter");    //索引为1
            person.add("annie");    //索引为2
            person.add("martin");   //索引为3
            person.add("marry");    //索引为4
            
            person.remove(3);   //.remove(index)
            person.remove("marry");     //.remove(Object o)
            
            String per="";
            per=person.get(1);
            System.out.println(per);    ////.get(index)
            
            for (int i = 0; i < person.size(); i++) {
                System.out.println(person.get(i));  //.get(index)
            }

 
2.list中是否包含某个元素;
方法:.contains(Object o); 返回true或者false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List<String> fruits=new ArrayList<>();
            fruits.add("苹果");
            fruits.add("香蕉");
            fruits.add("桃子");
            //for循环遍历list
            for (int i = 0; i < fruits.size(); i++) {
                System.out.println(fruits.get(i));
            }
            String appleString="苹果";
            //true or false
            System.out.println("fruits中是否包含苹果:"+fruits.contains(appleString));
            
            if (fruits.contains(appleString)) {
                System.out.println("我喜欢吃苹果");
            }else {
                System.out.println("我不开心");
            }

 
3.list中根据索引将元素数值改变(替换);
注意 .set(index, element); 和 .add(index, element); 的不同;

1
2
3
4
5
6
7
8
9
10
11
12
String a="白龙马", b="沙和尚", c="八戒", d="唐僧", e="悟空";
            List<String> people=new ArrayList<>();
            people.add(a);
            people.add(b);
            people.add(c);
            people.set(0, d);   //.set(index, element);     //将d唐僧放到list中索引为0的位置,替换a白龙马
            people.add(1, e);   //.add(index, element);     //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位
            
            //增强for循环遍历list
            for(String str:people){
                System.out.println(str);
            }

 
4.list中查看(判断)元素的索引; 
注意:.indexOf(); 和  lastIndexOf()的不同;

1
2
3
4
5
6
7
8
9
10
List<String> names=new ArrayList<>();
            names.add("刘备");    //索引为0
            names.add("关羽");    //索引为1
            names.add("张飞");    //索引为2
            names.add("刘备");    //索引为3
            names.add("张飞");    //索引为4
            System.out.println(names.indexOf("刘备"));
            System.out.println(names.lastIndexOf("刘备"));
            System.out.println(names.indexOf("张飞"));
            System.out.println(names.lastIndexOf("张飞"));

 
5.根据元素索引位置进行的判断;

1
2
3
4
5
6
7
if (names.indexOf("刘备")==0) {
    System.out.println("刘备在这里");
}else if (names.lastIndexOf("刘备")==3) {
    System.out.println("刘备在那里");
}else {
    System.out.println("刘备到底在哪里?");
}

 
6.利用list中索引位置重新生成一个新的list(截取集合);
方法: .subList(fromIndex, toIndex);  .size() ; 该方法得到list中的元素数的和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List<String> phone=new ArrayList<>();
            phone.add("三星");    //索引为0
            phone.add("苹果");    //索引为1
            phone.add("锤子");    //索引为2
            phone.add("华为");    //索引为3
            phone.add("小米");    //索引为4
            //原list进行遍历
            for(String pho:phone){
                System.out.println(pho);
            }
            //生成新list
            phone=phone.subList(14);  //.subList(fromIndex, toIndex)      //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3
            for (int i = 0; i < phone.size(); i++) { // phone.size() 该方法得到list中的元素数的和
                System.out.println("新的list包含的元素是"+phone.get(i));
            }

 
7.对比两个list中的所有元素;
//两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象

1
2
3
4
5
6
7
8
9
10
11
//1.<br>if (person.equals(fruits)) {
    System.out.println("两个list中的所有元素相同");
}else {
    System.out.println("两个list中的所有元素不一样");
}
//2.       
if (person.hashCode()==fruits.hashCode()) {
    System.out.println("我们相同");
}else {
    System.out.println("我们不一样");
}

 
8.判断list是否为空;
//空则返回true,非空则返回false

1
2
3
4
5
if (person.isEmpty()) {
    System.out.println("空的");
}else {
    System.out.println("不是空的");
}

 
9.返回Iterator集合对象;

1
System.out.println("返回Iterator集合对象:"+person.iterator());

 
1+0.将集合转换为字符串;

1
2
3
String liString="";
liString=person.toString();
System.out.println("将集合转换为字符串:"+liString);

 
11.将集合转换为数组;

1
System.out.println("将集合转换为数组:"+person.toArray());

 
12.集合类型转换;

1
2
3
4
5
6
7
8
9
10
//1.默认类型
List<Object> listsStrings=new ArrayList<>();
  for (int i = 0; i < person.size(); i++) {
    listsStrings.add(person.get(i));
}
//2.指定类型
List<StringBuffer> lst=new ArrayList<>();
  for(String string:person){
  lst.add(StringBuffer(string));
}

 
13.去重复;

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
List<String> lst1=new ArrayList<>();
            lst1.add("aa");
            lst1.add("dd");
            lst1.add("ss");
            lst1.add("aa");
            lst1.add("ss");
                   //方法 1.
            for (int i = 0; i <lst1.size()-1; i++) {
                for (int j = lst1.size()-1; j >i; j--) {
                    if (lst1.get(j).equals(lst1.get(i))) {
                        lst1.remove(j);
                    }
                }
            }
            System.out.println(lst1);
            
                   //方法 2.
            List<String> lst2=new ArrayList<>();
            for (String s:lst1) {
                if (Collections.frequency(lst2, s)<1) {
                    lst2.add(s);
                }
            }
            System.out.println(lst2);

 
 
附完整代码:

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package MyTest01;
import java.util.ArrayList;
import java.util.List;
public class ListTest01 {
    public static void main(String[] args) {
        
            //list中添加,获取,删除元素
            List<String> person=new ArrayList<>();
            person.add("jackie");   //索引为0  //.add(e)
            person.add("peter");    //索引为1
            person.add("annie");    //索引为2
            person.add("martin");   //索引为3
            person.add("marry");    //索引为4
            
            person.remove(3);   //.remove(index)
            person.remove("marry");     //.remove(Object o)
            
            String per="";
            per=person.get(1);
            System.out.println(per);    ////.get(index)
            
            for (int i = 0; i < person.size(); i++) {
                System.out.println(person.get(i));  //.get(index)
            }
            
            
        
            //list总是否包含某个元素
            List<String> fruits=new ArrayList<>();
            fruits.add("苹果");
            fruits.add("香蕉");
            fruits.add("桃子");
            //for循环遍历list
            for (int i = 0; i < fruits.size(); i++) {
                System.out.println(fruits.get(i));
            }
            String appleString="苹果";
            //true or false
            System.out.println("fruits中是否包含苹果:"+fruits.contains(appleString));
            
            if (fruits.contains(appleString)) {
                System.out.println("我喜欢吃苹果");
            }else {
                System.out.println("我不开心");
            }
            
            //list中根据索引将元素数值改变(替换)
            String a="白龙马", b="沙和尚", c="八戒", d="唐僧", e="悟空";
            List<String> people=new ArrayList<>();
            people.add(a);
            people.add(b);
            people.add(c);
            people.set(0, d);   //.set(index, element)      //将d唐僧放到list中索引为0的位置,替换a白龙马
            people.add(1, e);   //.add(index, element);     //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位
            
            //增强for循环遍历list
            for(String str:people){
                System.out.println(str);
            }
            
            //list中查看(判断)元素的索引
            List<String> names=new ArrayList<>();
            names.add("刘备");    //索引为0
            names.add("关羽");    //索引为1
            names.add("张飞");    //索引为2
            names.add("刘备");    //索引为3
            names.add("张飞");    //索引为4
            System.out.println(names.indexOf("刘备"));
            System.out.println(names.lastIndexOf("刘备"));
            System.out.println(names.indexOf("张飞"));
            System.out.println(names.lastIndexOf("张飞"));
            
            //根据元素索引位置进行的判断
            if (names.indexOf("刘备")==0) {
                System.out.println("刘备在这里");
            }else if (names.lastIndexOf("刘备")==3) {
                System.out.println("刘备在那里");
            }else {
                System.out.println("刘备到底在哪里?");
            }
            
            //利用list中索引位置重新生成一个新的list(截取集合)
            List<String> phone=new ArrayList<>();
            phone.add("三星");    //索引为0
            phone.add("苹果");    //索引为1
            phone.add("锤子");    //索引为2
            phone.add("华为");    //索引为3
            phone.add("小米");    //索引为4
            //原list进行遍历
            for(String pho:phone){
                System.out.println(pho);
            }
            //生成新list
            phone=phone.subList(14);  //.subList(fromIndex, toIndex)      //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3
            for (int i = 0; i < phone.size(); i++) { // phone.size() 该方法得到list中的元素数的和
                System.out.println("新的list包含的元素是"+phone.get(i));
            }
            
            //对比两个list中的所有元素
            //两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象
            if (person.equals(fruits)) {
                System.out.println("两个list中的所有元素相同");
            }else {
                System.out.println("两个list中的所有元素不一样");
            }
            
            if (person.hashCode()==fruits.hashCode()) {
                System.out.println("我们相同");
            }else {
                System.out.println("我们不一样");
            }
            
            
            //判断list是否为空
            //空则返回true,非空则返回false
            if (person.isEmpty()) {
                System.out.println("空的");
            }else {
                System.out.println("不是空的");
            }
            
            //返回Iterator集合对象
            System.out.println("返回Iterator集合对象:"+person.iterator());
            
            //将集合转换为字符串
            String liString="";
            liString=person.toString();
            System.out.println("将集合转换为字符串:"+liString);
            
            //将集合转换为数组,默认类型
            System.out.println("将集合转换为数组:"+person.toArray());
            
            ////将集合转换为指定类型(友好的处理)
            //1.默认类型
            List<Object> listsStrings=new ArrayList<>();
            for (int i = 0; i < person.size(); i++) {
                listsStrings.add(person.get(i));
            }
            //2.指定类型
            List<StringBuffer> lst=new ArrayList<>();
            for(String string:person){
                lst.add(StringBuffer(string));
            }
            
            
            
            
    }
    private static StringBuffer StringBuffer(String string) {
        return null;
    }
    }

Java中List和ArrayList的区别

List是一个接口,而ArrayList是List接口的一个实现类。
ArrayList类继承并实现了List接口。
因此,List接口不能被构造,也就是我们说的不能创建实例对象,但是我们可以像下面那样为List接口创建一个指
向自己的对象引用,而ArrayList实现类的实例对象就在这充当了这个指向List接口的对象引用。
 
个人见解:
要是你已经学过了OOP,上面的部分是不难理解的,这是面向对象重要的知识点,面向对象最重要的就是多态,
我们都知道接口和抽象不能被实例化,但是它们可以创建一个指向自己的对象引用,它们的实现类或子类就在充当这
样的角色,我想这就是面向对象编程中多态的优势。前些日子在学习UML建模语言和Java设计模式的时候,深深地的
体会到了面向对象编程的好处,Java集合框架中用到也不足为奇,Java本身就是面向对象的编程语言。
上面的理解可能有点难度,但是我们找一个具体的实例,就会理解起来比较容易。我们定义一个动物的抽象类
Animal,再定义一个继承自Animal基类的Dog类,看下面的代码就会理解抽象类和接口不能被实例化:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<span style="font-size:18px;">public class Test{
    public static void main(String[] args){
        Animal a1 = new Animal();//编译出错
        Animal a2 = new Dog();
    }
}
abstract class Animal{
    //动物名字
    String name;
    
    //动物叫声
    public void shout(){
        System.out.println("叫声...");
    }
}
class Dog extends Animal{
    //狗类独有的方法
    public void guard(){
        System.out.println("狗有看门的独特本领!");
    }
}</span>

编译结果:
 
\
 
List list;//正确,list = null;
List list = new List();//是错误的用法
List list = new ArrayList();这句创建了一个ArrayList实现类的对象后把它上溯到了List接口。此时它就是一个List对
象了,它有些ArrayList类具有的,但是List接口没有的属性和方法,它就不能再用了。 而ArrayList list=newArrayList();
创建一对象则保留了ArrayList的所有属性和方法。
 
个人见解
我们继续上面的例子,如果我们创建的是抽象类的对象引用,那么这个对象只能调用自己的非抽象方法,下面的
是shout()方法,不能调用继承它的子类的独有的方法,在下面的就是guard()方法不能被a1调用,继续测试代码:
 

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
<span style="font-size:18px;">public class Test{
    public static void main(String[] args){
        Animal a1 = new Dog();
        a1.shout();//编译通过
        //a1.guard();//编译出错
    }
}
abstract class Animal{
    //动物名字
    String name;
    
    //动物叫声
    public void shout(){
        System.out.println("叫声...");
    }
}
class Dog extends Animal{
    //狗类独有的方法
    public void guard(){
        System.out.println("狗有看门的独特本领!");
    }
}
</span>

 
编译结果:
\
如果我们采用Dog d1 = new Dog();那么d1可以调用抽象类和子类的所有属性和方法,这里不再测试。
 
这是一个例子:
 

1
2
3
4
5
6
7
8
9
10
<span style="font-size:18px;">import java.util.*;
public class Demo{
    public static void main(String[] args){
        List list = new ArrayList();
                ArrayList arrayList = new ArrayList();
                list.trimToSize();//错误,没有该方法。
                arrayList.trimToSize();//ArrayList里有该方法。
}
}</span>

 
编译一下就知道结果了。
 
个人见解
我刚在前面的文章里面把Java API中List接口和ArrayList实现类的方法都列出来了,可以看到List接口中并没有
trimToSize()方法,但这个方法在它的实现类ArrayList中有。因此编译的结果为:
\
 
如果是下面这个样子的:
List a=new ArrayList();
则a拥有List的所有属性和方法,不会拥有其实现类ArrayList的独有的属性和方法。
如果List与ArrayList中有相同的属性(如int i),有相同的方法(如void f()),
则a.i是调用了List中的i
a.f()是调用了ArrayList中的f();
—————————————————————————————————————-
问题的关键:
为什么要用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
问题就在于List接口有多个实现类,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类,如
LinkedList或者Vector等等,这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根
本不需要改动。
假设你开始用ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了ArrayList实现类特有的方法
和属性。
 
个人见解
上面的说明,我是在看了设计模式才恍然大悟的,设计模式的原则和理念果然是强大的,只有好好学习了面向对
象原则和设计模式,那么理解上面的就不再是难度,这样的好处是为了代码的可维护性,可复用性,可扩展性以及灵
活性,再者就是这符合了里氏代换原则和开闭原则。看来学习设计模式好处是大大的。
 
 
地区用List arr = new ArrayList();定义;行业用ArrayList arr = new ArrayList();定义;则说明,行业里用到了ArrayList的
特殊的方法.
另外的例子就是,在类的方法中,如下声明:
private void doMyAction(List list){}
这样这个方法能处理所有实现了List接口的类,一定程度上实现了泛型函数.
如果开发的时候觉得ArrayList,HashMap的性能不能满足你的需要,可以通过实现List,Map(或者Collection)来定制
你的自定义类.
个人见解
正因为List是接口,所以它的扩展性是良好的,这是面向对象编程最大的改变,也是它的核心,在这里我是体会
到了一句话,就是Java集合框架的学习最难体现你学习Java语言的程序都多深,看来我以前学习的程度只是停留在入
门级别了,这几天可要好好再温习重新认识一番Java集合框架了。
可能理解不是很深,对于原文的理解也就这些了,不对的地方自己会及时更正。本来想画图说明的,但是由于自
己UML学习的不怎样,就没有去认真的画,以后还是多多学习画图的。

赞(0) 打赏
未经允许不得转载:openSL » 数据结构:JAVA中的List

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏