JavaRush /Java 博客 /Random-ZH /Java中的ArrayList类

Java中的ArrayList类

已在 Random-ZH 群组中发布
你好!在之前的讲座中,我们详细研究了数组等数据结构,并查看了使用它们的常见示例。但这种数据结构有很多缺点。Java 中 ArrayList 的出现给了他们答案。简而言之,Java 中的 ArrayList 是一个“升级版”的数组,具有很多新功能。ArrayList 类 - 1

Java Arraylist 与常规数组有何不同?

一般来说,数组非常方便,而且正如您已经注意到的,您可以用它们做很多事情:)但是,数组也有许多缺点。
  • 尺寸有限。您需要在创建数组的阶段就知道它应包含多少个单元格。如果您低估了所需的数量,则将没有足够的空间。如果你高估了它,数组将保持一半为空,这还不错。毕竟,事实证明您也会为其分配比必要的更多的内存。
  • 数组没有添加元素的方法。您始终必须显式指定要添加元素的单元格的索引。如果您不小心指定了某个已占用的单元格所需的值,它将被覆盖。
  • 没有方法可以删除元素。该值只能“清零”。
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;



       System.out.println(Arrays.toString(cats));
   }

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
结论:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
使用ArrayList 可以消除所有这些缺点。它的创建非常简单:
ArrayList<Cat> cats = new ArrayList<Cat>();
现在我们已经创建了一个列表来存储对象Cat注意:我们不指定 ArrayList 的大小,因为它是可自动扩展的。这怎么可能?容易地。你会感到惊讶,但是 ArrayList 是基于普通数组的:) 是的,里面有一个数组,里面存储了我们的元素。但 ArrayList 有一个特殊的机制来使用它:
  • 当这个内部数组已满时,ArrayList 会在其内部创建一个新数组。它的大小 = (旧数组的大小 * 1.5) +1。
  • 所有数据都从旧数组复制到新数组
  • 旧数组被垃圾收集器删除。
由于这种机制,ArrayList(与数组相反)实现了添加新元素的方法。这是一个方法add()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Hippopotamus"));
}
新元素将添加到列表的末尾。现在不存在溢出的风险,所以这个机制是完全安全的。顺便说一句,ArrayList 不仅可以通过索引搜索对象,反之亦然——它可以通过引用对象来查找 ArrayList 中对象的索引!为此,它实现了以下方法indexOf():我们向其传递一个指向所需对象的链接,然后indexOf()它将其索引返回给我们:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
结论:

0
没错,对象thomas实际上是存储在cell中的0。数组不仅有缺点,也有无可置疑的优点。其中之一是通过索引搜索元素。由于我们指向的是索引,即内存中的特定地址,所以这样的数组查找速度非常快。Java中的ArrayList也可以做到这一点!为此,它实现了一个方法get()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
结论:

Cat{name='Бегемот'}
此外,您还可以轻松找出 ArrayList 是否包含特定对象。这是使用以下方法完成的contains()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   cats.remove(pushok);
   System.out.println(cats.contains(pushok));
}
boolean该方法检查该元素是否包含在 ArrayList 的内部数组中,并以-true或 的 形式返回结果false。结论:

false
关于插入的另一个重要的事情。ArrayList 不仅允许您在数组末尾插入数据,还可以通过索引插入到任何单元格中。它有两种方法:
  • add(int index, Cat element)
  • set(int index, Cat element)
对于两者,您可以传递要插入的单元格的索引以及对象本身的链接。不同之处在于粘贴set()会覆盖单元格中存储的旧值。插入add()首先会将所有元素从数组开始移动[index]到数组末尾,并将所需的对象添加到生成的空单元格中。这是一个例子:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.set(0, philipp);//Now we have a list of 2 cats. We add the 3rd via set:

   System.out.println(cats.toString());
}
结论:

[[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Бегемот'}]
我们有 2 只猫的列表,我们通过该方法将另一只猫插入set()到单元格中0。结果,存储在该单元格中的旧值被新值替换。
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.add(0, philipp);//Now we have a list of 2 cats. Add the 3rd via add

   System.out.println(cats.toString());
}
但它的add()作用不同。他将所有元素向右移动,然后将新值写入单元格中0。结论:

[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Томас'}, Cat{name='Бегемот'}]
要完全清除列表,请使用以下方法clear()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   cats.clear();

   System.out.println(cats.toString());
}
结论:

[]
所有内容已从列表中删除。顺便说一句,请注意:与数组不同,在 ArrayList 中,toString() 方法被重写并立即以字符串格式显示列表。对于数组,我们必须使用 Arrays 类来实现此目的。由于我们还记得数组:在 Java 中,您可以轻松地在数组和 ArrayList 之间“切换”,即将一个数组转换为另一个数组。Arrays 类有一个方法可以实现此目的,即 Arrays.asList()。在它的帮助下,我们以列表的形式获取数组的内容并将其传递给 ArrayList 的构造函数:
public static void main(String[] args) {

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   Cat[] catsArray = {thomas, behemoth, philipp, pushok};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
结论:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
您也可以执行相反的操作 - 从 ArrayList 对象获取数组。为此,请使用 toArray() 方法:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   Cat[] catsArray = cats.toArray(new Cat[0]);

   System.out.println(Arrays.toString(catsArray));
}
请注意:我们将一个空数组传递给 toArray() 方法。这不是一个错误。在 ArrayList 类内部,此方法的实现方式是传递空数组以提高其性能。现在,请记住这一点以备将来使用(但您也可以传输特定大小,它会起作用)。说到尺寸。可以使用以下方法找到列表的当前大小size()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   System.out.println(cats.size());
}
这里需要理解的是,与length数组属性不同,ArrayList.size() 方法返回的正是元素的数量,而不是初始容量,因为我们在创建 ArrayList 时没有指定它。顺便说一下,一般都可以标明的。ArrayList有一个相应的构造函数。但它在添加新元素方面的行为不会改变:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>(2);//create an ArrayList with an initial capacity of 2


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   System.out.println(cats.size());
}
控制台输出:

4
我们创建了一个包含 2 个元素的列表,但是当我们需要它时,它很容易扩展。另外,如果我们最初创建的列表非常小,那么它就必须更频繁地进行扩展操作,这会消耗一定的资源。在本次讲座中,我们几乎没有涉及从 ArrayList 中删除元素的过程。当然,这并不是因为健忘。这个主题已被分成一个单独的讲座,您可以进一步阅读:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION