天津南开区网站建设公司,可信赖的深圳网站建设,wordpress开启伪静态找不到页面,浏览器怎么打开网站本章概要
添加元素组集合的打印列表 List
添加元素组
在 java.util 包中的 Arrays 和 Collections 类中都有很多实用的方法#xff0c;可以在一个 Collection 中添加一组元素。
Arrays.asList() 方法接受一个数组或是逗号分隔的元素列表#xff08;使用可变参数#xff…本章概要
添加元素组集合的打印列表 List
添加元素组
在 java.util 包中的 Arrays 和 Collections 类中都有很多实用的方法可以在一个 Collection 中添加一组元素。
Arrays.asList() 方法接受一个数组或是逗号分隔的元素列表使用可变参数并将其转换为 List 对象。 Collections.addAll() 方法接受一个 Collection 对象以及一个数组或是一个逗号分隔的列表将其中元素添加到 Collection 中。下边的示例展示了这两个方法以及更通用的 、所有 Collection 类型都包含的addAll() 方法
// collections/AddingGroups.java
// Adding groups of elements to Collection objects
import java.util.*;public class AddingGroups {public static void main(String[] args) {CollectionInteger collection new ArrayList(Arrays.asList(1, 2, 3, 4, 5));Integer[] moreInts {6, 7, 8, 9, 10};collection.addAll(Arrays.asList(moreInts));// Runs significantly faster, but you cant// construct a Collection this way:Collections.addAll(collection, 11, 12, 13, 14, 15);Collections.addAll(collection, moreInts);// Produces a list backed by an array:ListInteger list Arrays.asList(16, 17, 18, 19, 20);list.set(1, 99); // OK -- modify an element// list.add(21); // Runtime error; the underlying// array cannot be resized.}
}Collection 的构造器可以接受另一个 Collection用它来将自身初始化。因此可以使用 Arrays.asList() 来为这个构造器产生输入。但是 Collections.addAll() 运行得更快而且很容易构建一个不包含元素的 Collection 然后调用 Collections.addAll() 因此这是首选方式。
Collection.addAll() 方法只能接受另一个 Collection 作为参数因此它没有 Arrays.asList() 或 Collections.addAll() 灵活。这两个方法都使用可变参数列表。
也可以直接使用 Arrays.asList() 的输出作为一个 List 但是这里的底层实现是数组没法调整大小。如果尝试在这个 List 上调用 add() 或 remove()由于这两个方法会尝试修改数组大小所以会在运行时得到“Unsupported Operation不支持的操作”错误
// collections/AsListInference.java
import java.util.*;class Snow {
}class Powder extends Snow {
}class Light extends Powder {
}class Heavy extends Powder {
}class Crusty extends Snow {
}class Slush extends Snow {
}public class AsListInference {public static void main(String[] args) {ListSnow snow1 Arrays.asList(new Crusty(), new Slush(), new Powder());//- snow1.add(new Heavy()); // ExceptionListSnow snow2 Arrays.asList(new Light(), new Heavy());//- snow2.add(new Slush()); // ExceptionListSnow snow3 new ArrayList();Collections.addAll(snow3,new Light(), new Heavy(), new Powder());snow3.add(new Crusty());// Hint with explicit type argument specification:ListSnow snow4 Arrays.SnowasList(new Light(), new Heavy(), new Slush());//- snow4.add(new Powder()); // Exception}
}在 snow4 中注意 Arrays.asList() 中间的“暗示”即 Snow 告诉编译器 Arrays.asList() 生成的结果 List 类型的实际目标类型是什么。这称为_显式类型参数说明_explicit type argument specification。
集合的打印
必须使用 Arrays.toString() 来生成数组的可打印形式。但是打印集合无需任何帮助。下面是一个例子这个例子中也介绍了基本的Java集合
// collections/PrintingCollections.java
// Collections print themselves automatically
import java.util.*;public class PrintingCollections {static Collection fill(CollectionString collection) {collection.add(rat);collection.add(cat);collection.add(dog);collection.add(dog);return collection;}static Map fill(MapString, String map) {map.put(rat, Fuzzy);map.put(cat, Rags);map.put(dog, Bosco);map.put(dog, Spot);return map;}public static void main(String[] args) {System.out.println(fill(new ArrayList()));System.out.println(fill(new LinkedList()));System.out.println(fill(new HashSet()));System.out.println(fill(new TreeSet()));System.out.println(fill(new LinkedHashSet()));System.out.println(fill(new HashMap()));System.out.println(fill(new TreeMap()));System.out.println(fill(new LinkedHashMap()));}
}这显示了Java集合库中的两个主要类型。它们的区别在于集合中的每个“槽”slot保存的元素个数。 Collection 类型在每个槽中只能保存一个元素。此类集合包括 List 它以特定的顺序保存一组元素 Set 其中元素不允许重复 Queue 只能在集合一端插入对象并从另一端移除对象就本例而言这只是查看序列的另一种方式因此并没有显示它。 Map 在每个槽中存放了两个元素即_键_ (key)和与之关联的_值_ (value)。
默认的打印行为使用集合提供的 toString() 方法即可生成可读性很好的结果。 Collection 打印出的内容用方括号括住每个元素由逗号分隔。 Map 则由大括号括住每个键和值用等号连接键在左侧值在右侧。
第一个 fill() 方法适用于所有类型的 Collection 这些类型都实现了 add() 方法以添加新元素。
ArrayList 和 LinkedList 都是 List 的类型从输出中可以看出它们都按插入顺序保存元素。两者之间的区别不仅在于执行某些类型的操作时的性能而且 LinkedList 包含的操作多于 ArrayList 。本章后面将对这些内容进行更全面的探讨。
HashSet TreeSet 和 LinkedHashSet 是 Set 的类型。从输出中可以看到 Set 仅保存每个相同项中的一个并且不同的 Set 实现存储元素的方式也不同。 HashSet 使用相当复杂的方法存储元素现在只需要知道这种技术是检索元素的最快方法因此存储顺序看上去没有什么意义通常只关心某事物是否是 Set 的成员而存储顺序并不重要。如果存储顺序很重要则可以使用 TreeSet 它把对象按照比较规则来排序还有 LinkedHashSet 它把对象按照被添加的先后顺序来排序。
Map 也称为_关联数组_使用_键_来查找对象就像一个简单的数据库。所关联的对象称为_值_。 假设有一个 Map 将美国州名与它们的首府联系在一起如果想要俄亥俄州Ohio的首府可以用“Ohio”作为键来查找几乎就像使用数组下标一样。正是由于这种行为对于每个键 Map 只存储一次。
Map.put(key, value) 添加一个所想要添加的值并将它与一个键用来查找值相关联。 Map.get(key) 生成与该键相关联的值。上面的示例仅添加键值对并没有执行查找。这将在稍后展示。
请注意这里没有指定或考虑 Map 的大小因为它会自动调整大小。 此外 Map 还知道如何打印自己它会显示相关联的键和值。
本例使用了 Map 的三种基本风格 HashMap TreeMap 和 LinkedHashMap 。
键和值保存在 HashMap 中的顺序不是插入顺序因为 HashMap 实现使用了非常快速的算法来控制顺序。 TreeMap 把所有的键按照比较规则来排序 LinkedHashMap 在保持 HashMap 查找速度的同时按照键的插入顺序来排序。
列表List
List承诺将元素保存在特定的序列中。 List 接口在 Collection 的基础上添加了许多方法允许在 List 的中间插入和删除元素。
有两种类型的 List
基本的 ArrayList 擅长随机访问元素但在 List 中间插入和删除元素时速度较慢。LinkedList 它通过代价较低的在 List 中间进行的插入和删除操作提供了优化的顺序访问。 LinkedList 对于随机访问来说相对较慢但它具有比 ArrayList 更大的特征集。
下面的示例导入 typeinfo.pets 超前使用了类型信息一章中的类库。这个类库包含了 Pet 类层次结构以及用于随机生成 Pet 对象的一些工具类。此时不需要了解完整的详细信息只需要知道两点
有一个 Pet 类以及 Pet 的各种子类型。静态的 new PetCreator().list() 方法返回一个填充了随机选取的 Pet 对象的 ArrayList ListFeatures.java import java.util.*;public class ListFeatures {public static void main(String[] args) {Random rand new Random(47);ListPet pets new PetCreator().list(7);System.out.println(1: pets);Hamster h new Hamster();pets.add(h); // Automatically resizesSystem.out.println(2: pets);System.out.println(3: pets.contains(h));pets.remove(h); // Remove by objectPet p pets.get(2);System.out.println(4: p pets.indexOf(p));Pet cymric new Cymric();System.out.println(5: pets.indexOf(cymric));System.out.println(6: pets.remove(cymric));// Must be the exact object:System.out.println(7: pets.remove(p));System.out.println(8: pets);pets.add(3, new Mouse()); // Insert at an indexSystem.out.println(9: pets);ListPet sub pets.subList(1, 4);System.out.println(subList: sub);System.out.println(10: pets.containsAll(sub));Collections.sort(sub); // In-place sortSystem.out.println(sorted subList: sub);// Order is not important in containsAll():System.out.println(11: pets.containsAll(sub));Collections.shuffle(sub, rand); // Mix it upSystem.out.println(shuffled subList: sub);System.out.println(12: pets.containsAll(sub));ListPet copy new ArrayList(pets);sub Arrays.asList(pets.get(1), pets.get(4));System.out.println(sub: sub);copy.retainAll(sub);System.out.println(13: copy);copy new ArrayList(pets); // Get a fresh copycopy.remove(2); // Remove by indexSystem.out.println(14: copy);copy.removeAll(sub); // Only removes exact objectsSystem.out.println(15: copy);copy.set(1, new Mouse()); // Replace an elementSystem.out.println(16: copy);copy.addAll(2, sub); // Insert a list in the middleSystem.out.println(17: copy);System.out.println(18: pets.isEmpty());pets.clear(); // Remove all elementsSystem.out.println(19: pets);System.out.println(20: pets.isEmpty());pets.addAll(new PetCreator().list(4));System.out.println(21: pets);Object[] o pets.toArray();System.out.println(22: o[3]);Pet[] pa pets.toArray(new Pet[0]);System.out.println(23: pa[3].id());}
}其它相关类 Cat.java public class Cat extends Pet {public Cat(String name) { super(name); }public Cat() { super(); }
}Creator.java import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;public abstract class Creator implements SupplierPet {private Random rand new Random(47);// The different types of Pet to create:public abstract ListClass? extends Pet types();Overridepublic Pet get() { // Create one random Petint n rand.nextInt(types().size());try {return types().get(n).getConstructor().newInstance();} catch (InstantiationException |NoSuchMethodException |InvocationTargetException |IllegalAccessException e) {throw new RuntimeException(e);}}public StreamPet stream() {return Stream.generate(this);}public Pet[] array(int size) {return stream().limit(size).toArray(Pet[]::new);}public ListPet list(int size) {return stream().limit(size).collect(Collectors.toCollection(ArrayList::new));}
}Cymric.java public class Cymric extends Manx {public Cymric(String name) { super(name); }public Cymric() { super(); }
}Dog.java public class Dog extends Pet {public Dog(String name) { super(name); }public Dog() { super(); }
}EgyptianMau.java public class EgyptianMau extends Cat {public EgyptianMau(String name) { super(name); }public EgyptianMau() { super(); }
}Hamster.java public class Hamster extends Rodent {public Hamster(String name) { super(name); }public Hamster() { super(); }
}Individual.java import java.util.Objects;public class Individual implements ComparableIndividual {private static long counter 0;private final long id counter;private String name;public Individual(String name) {this.name name;}// name is optional:public Individual() {}Overridepublic String toString() {return getClass().getSimpleName() (name null ? : name);}public long id() {return id;}Overridepublic boolean equals(Object o) {return o instanceof Individual Objects.equals(id, ((Individual) o).id);}Overridepublic int hashCode() {return Objects.hash(name, id);}Overridepublic int compareTo(Individual arg) {// Compare by class name first:String first getClass().getSimpleName();String argFirst arg.getClass().getSimpleName();int firstCompare first.compareTo(argFirst);if (firstCompare ! 0) {return firstCompare;}if (name ! null arg.name ! null) {int secondCompare name.compareTo(arg.name);if (secondCompare ! 0) {return secondCompare;}}return (arg.id id ? -1 : (arg.id id ? 0 : 1));}
}Manx.java public class Manx extends Cat {public Manx(String name) { super(name); }public Manx() { super(); }
}Mouse.java public class Mouse extends Rodent {public Mouse(String name) { super(name); }public Mouse() { super(); }
}Mutt.java public class Mutt extends Dog {public Mutt(String name) { super(name); }public Mutt() { super(); }
}Pet.java public class Pet extends Individual {public Pet(String name) {super(name);}public Pet() {super();}
}PetCreator.java import java.util.*;public class PetCreator extends Creator {// No try block needed.public static finalListClass? extends Pet ALL_TYPES Collections.unmodifiableList(Arrays.asList(Pet.class, Dog.class, Cat.class, Rodent.class,Mutt.class, Pug.class, EgyptianMau.class,Manx.class, Cymric.class, Rat.class,Mouse.class, Hamster.class));// Types for random creation:private static finalListClass? extends Pet TYPES ALL_TYPES.subList(ALL_TYPES.indexOf(Mutt.class),ALL_TYPES.size());Overridepublic ListClass? extends Pet types() {return TYPES;}public static void main(String[] args) {System.out.println(TYPES);ListPet pets new PetCreator().list(7);System.out.println(pets);}
}
/* Output:
[class reflection.pets.Mutt, class reflection.pets.Pug,
class reflection.pets.EgyptianMau, class
reflection.pets.Manx, class reflection.pets.Cymric, class
reflection.pets.Rat, class reflection.pets.Mouse, class
reflection.pets.Hamster]
[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug]
*/Pug.java public class Pug extends Dog {public Pug(String name) { super(name); }public Pug() { super(); }
}Rat.java public class Rat extends Rodent {public Rat(String name) { super(name); }public Rat() { super(); }
}Rodent.java public class Rodent extends Pet {public Rodent(String name) { super(name); }public Rodent() { super(); }
}打印内容如下 打印行都编了号因此可从输出追溯到源代码。 第 1 行输出展示了原始的由 Pet 组成的 List 。 与数组不同 List 可以在创建后添加或删除元素并自行调整大小。这正是它的重要价值一种可修改的序列。在第 2 行输出中可以看到添加一个 Hamster 的结果该对象将被追加到列表的末尾。
可以使用 contains() 方法确定对象是否在列表中。如果要删除一个对象可以将该对象的引用传递给 remove() 方法。同样如果有一个对象的引用可以使用 indexOf() 在 List 中找到该对象所在位置的下标号如第 4 行输出所示中所示。
当确定元素是否是属于某个 List 寻找某个元素的索引以及通过引用从 List 中删除元素时都会用到 equals() 方法根类 Object 的一个方法。每个 Pet 被定义为一个唯一的对象所以即使列表中已经有两个 Cymrics 如果再创建一个新的 Cymric 对象并将其传递给 indexOf() 方法结果仍为 -1 表示未找到并且尝试调用 remove() 方法来删除这个对象将返回 false 。对于其他类 equals() 的定义可能有所不同。例如如果两个 String 的内容相同则这两个 String 相等。因此为了防止出现意外请务必注意 List 行为会根据 equals() 行为而发生变化。
第 7、8 行输出展示了删除与 List 中的对象完全匹配的对象是成功的。
可以在 List 的中间插入一个元素就像在第 9 行输出和它之前的代码那样。但这会带来一个问题对于 LinkedList 在列表中间插入和删除都是廉价操作在本例中除了对列表中间进行的真正的随机访问但对于 ArrayList 这可是代价高昂的操作。这是否意味着永远不应该在 ArrayList 的中间插入元素并最好是转换为 LinkedList 不它只是意味着你应该意识到这个问题如果你开始在某个 ArrayList 中间执行很多插入操作并且程序开始变慢那么你应该看看你的 List 实现有可能就是罪魁祸首发现此类瓶颈的最佳方式是使用分析器 profiler。优化是一个很棘手的问题最好的策略就是置之不顾直到发现必须要去担心它了尽管去理解这些问题总是一个很好的主意。
subList() 方法可以轻松地从更大的列表中创建切片当将切片结果传递给原来这个较大的列表的 containsAll() 方法时很自然地会得到 true。请注意顺序并不重要在第 11、12 行输出中可以看到在 sub 上调用直观命名的 Collections.sort() 和 Collections.shuffle() 方法不会影响 containsAll() 的结果。 subList() 所产生的列表的幕后支持就是原始列表。因此对所返回列表的更改都将会反映在原始列表中反之亦然。
retainAll() 方法实际上是一个“集合交集”操作在本例中它保留了同时在 copy 和 sub 中的所有元素。请再次注意所产生的结果行为依赖于 equals() 方法。
第 14 行输出展示了使用索引号来删除元素的结果与通过对象引用来删除元素相比它显得更加直观因为在使用索引时不必担心 equals() 的行为。
removeAll() 方法也是基于 equals() 方法运行的。 顾名思义它会从 List 中删除在参数 List 中的所有元素。
set() 方法的命名显得很不合时宜因为它与 Set 类存在潜在的冲突。在这里使用“replace”可能更适合因为它的功能是用第二个参数替换索引处的元素第一个参数。
第 17 行输出表明对于 List 有一个重载的 addAll() 方法可以将新列表插入到原始列表的中间位置而不是仅能用 Collection 的 addAll() 方法将其追加到列表的末尾。
第 18 - 20 行输出展示了 isEmpty() 和 clear() 方法的效果。
第 22、23 行输出展示了如何使用 toArray() 方法将任意的 Collection 转换为数组。这是一个重载方法其无参版本返回一个 Object 数组但是如果将目标类型的数组传递给这个重载版本那么它会生成一个指定类型的数组假设它通过了类型检查。如果参数数组太小而无法容纳 List 中的所有元素就像本例一样则 toArray() 会创建一个具有合适尺寸的新数组。 Pet 对象有一个 id() 方法可以在所产生的数组中的对象上调用这个方法。