集合Practices
1:集合Collection中存储的如果是自定义类的对象,需要自定义类重写哪个方法?为什么?
equals()
因为在进行比较(contains()方法的时候)的时候需要用equals()方法
List: equals()
Set(HastSet ):equals()和hashCode()因为在添加数据的时候set不可添加重复数据也要对比数据的哈希值
2:ArrayList,LinkedList,Vector三者的相同点与不同点?【面试题】
Vector:底层数据结构是数组结构。 jdk1.0版本。 线程安全的。 无论增删还是查询都非常慢。默认扩充为原来的2倍。 ArrayList:底层数据结构是数组结构。 线程不安全的。 所以ArrayList的出现替代了Vector, 但是查询的速度很快。默认扩充为原来的1.5倍。 LinkedList:底层是链表数据结构。 线程不安全的, 同时对元素的增删操作效率很高。但查询慢。 1、 线程同步,Vector线程安全,ArrayList线程不安全。 2、 效率问题,Vector效率低,ArrayList效率高。 3、 增长数量,Vector以2倍增长,ArrayList以1.5倍增长。
3: List 接口的常用方法有哪些?(增、删、改、查、插、长度、遍历)
增: add(Object obj) 删: remove(Object obj) 改: set(int index,Object obj) 查: get(int index) 插入: set(int index,Object obj) 长度: size() 不是底层数组的长度而是存储的元素个数 遍历: iterator() 迭代器 foreach
4: Set存储数据的特点是什么?常见的实现类有什么?说明一下彼此的特点。
set内的元素 ,无序的不可重复的
HashSet LinkedHashSet TreeSet
5:Map存储数据的特点是什么?并指明key,value,entry存储数据的特点。
数据的特点是双列数据以键值对的形式存在,存储key-value对数据。 key:无序的、不可重复的-Set存储 value:无序的、可重复的 –>Collection存储 Entry: key-value:无序的、不可重复 Set存储
6:描述HashMap的底层实现原理(jdk 8版)
HashMap hashmap = new HashMap(); 在实例化后底层不会和jdk7一样创建一样长度为16的数组 map.put(key1,value1); 添加元素时才创建一个底层长度为16的数组这个数组时Node[]: 首先调用key1所在类的hashcode()计算key1的哈希值,此哈希值经过某种算法之后得到存储在Node[]数组中的存放的位置 如果位置上的元素为空则添加元素成功-----情况1 如果此时位置上的数据不为空那么意味着这个位置上已经存在一个或者多个以链表形式或者红黑树形式存在的元素,那么比较key1和已经存在的一个或者多个元素的哈希值 如果key1的哈希值和当前存放元素的哈希值都不同那么添加成功----情况2 如果key1的哈希值和已经存在的某一个元素(key2--value2)的哈希值相同,那么调用equals(key2)方法继续比较 如果equals()返回false,此时key1---value1添加成功 ---- 情况3 如果equals()返回true 此时就是替换了,将value1替换成相同key值的value值,因为key值相同那就是value不同了(此时为key相同而value不同的替换操作) jdk8 new HashMap的时候没有创建底层长度为16的数据 ,当put操作的时候放在创建长度为16的数组 底层的数据不是Entry[]而时Node[] 数据存储的结构是:数据+链表+红黑树 因为二叉树存储的时候会很有序,例如小的全部放在右边或者左边,这样查找的时候只去那一边查找即可
7: Map中常用实现类有哪些?各自有什么特点?
HashMap: 作为Map的主要实现类 LinkedHashMap:保证在遍历map元素时,可以按照添加顺序实现遍历。 原因: 在原有的HaspMap底层结构基础上,添加一对指针,分别指向前一个后一个元素 对于频繁遍历的元素操作,此类执行效率高于HaspMap TreeMap: 可以按照添加的key--value来进行排序,实现排序(此时考虑key来排序) Hashtable: 古老的实现类,线程安全的效率低 不能存储null的key和value
8:如何遍历Map中的key-value对,代码实现
使用entrySet()获取键值对 public static void main(String[] args) { HashMap hashMap = new HashMap(); hashMap.put(1,"老张"); hashMap.put(2,"隔壁老王"); hashMap.put(3,"吉尔森"); hashMap.put(4,"特朗普"); Iterator iterator = hashMap.entrySet().iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } }
9:Collection和Collections的区别?
Collection: java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。
Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。 Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
Collection是集合类的上级接口,继承于他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
10:Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别
答:Set里的元素是不能重复的,用equals()方法判读两个Set是否相等 equals()和==方法决定引用值是否指向同一对象, equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值
==是用来判断两者是否是同一对象(同一事物),而equals是用来判断是否引用同一个对象。
再看一下Set里面存的是对象,还是对象的引用。根据java的存储机制可知,set里面存放的是对象的引用,
所以当两个元素只要满足了equals()时就已经指向同一个对象,也就出现了重复元素。所以应该用equals()来判断
觉得Set存放的是引用类型的数据,也就是对象的引用,所以区分重复与否用的是equals方法。
==判断的两个对象引用是否引用同一个对象,即判断地址是否相等,而equals方法(需要重写)判断的是对象实质内容是否相同。
11: List, Set, Map是否继承自Collection接口
答: List,Set是,Map不是
12:两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对
答:不对,有相同的hash code
13: 说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList : 底层是数组存储,线程不安全,查询的时候速度快
Vector 底层是数组存储,线程安全,无论是查询还是删除修改 速度都慢
LinkedList: 底层是链表存储,线程不安全,插入操作速度快
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,
但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),
通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
14: HashMap和Hashtable的区别
答: 1.HashMap与Hashtable都实现了Map接口。由于HashMap的非线程安全性,效率上可能高于Hashtable。Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 2. HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。 3.HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 4.Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。 5.Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
15:ArrayList和Vector的区别
ArrayList和Vector的区别 答:就ArrayList与Vector主要从二方面来说. 一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的 二.数据增长:当需要增长时,Vector默认增长为原来一倍(是一样长度的2倍),而ArrayList却是原来的一半(以前长度的1.5)
16:你所知道的集合类都有哪些?主要方法?
答:最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。
List 适用于按数值索引访问元素的情形。 Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。
17:定义一个Collection接口类型的变量,引用一个Set集合的实现类,实现添加单个元素,添加另一个集合,删除元素,判断集合中是否包含一个元素,
判断是否为空,清除集合,返回集合里元素的个数等常用操作。
public static void main(String[] args) { Set<Integer> one = new TreeSet<Integer>(); for (int i = 0; i < 5; i++) { one.add(i); } System.out.println(one); Set<Integer> two = new TreeSet<>(); two.add(5); two.add(9); two.add(8); two.addAll(one); System.out.println(two); for (Integer i:two ) { System.out.println(i + " "); } one.add(10); System.out.println("======="); System.out.println(one.size()); System.out.println(two.containsAll(one)); System.out.println(one.isEmpty()); two.clear(); System.out.println(two); }
18:创建Set接口的实现类,添加10个以上的元素,通过Iterator遍历此集合元素。
public static void main(String[] args) { HashSet hashSet = new HashSet(); for (int i = 0; i < 11 ; i++) { hashSet.add(i); } Iterator iterator = hashSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } }
19:创建Set接口的实现类,添加10个以上的元素,通过foreach遍历此集合元素。
public static void main(String[] args) { Set<Integer> hashSet = new HashSet(); for (int i = 0; i < 11 ; i++) { hashSet.add(i); } for (Integer i: hashSet ) { System.out.println(i); } }
20: 创建Set接口的实现类,添加10个以上的元素,要求能够排序。
可以排序的就要使用TreeSet了因为TreeSet是可以根据元素进行排序的 public static void main(String[] args) { TreeSet<Integer> treeSet = new TreeSet(); treeSet.add(234); treeSet.add(1); treeSet.add(345); treeSet.add(23); treeSet.add(90); treeSet.add(564); treeSet.add(12); treeSet.add(789); treeSet.add(35); System.out.println(treeSet); for (Integer i:treeSet ) { System.out.println(i); } }
21 : 创建Car类,包含name,price属性,构造器等方法,创建测试类,在main方法中创建Set接口的实现类,添加5个以上的Car对象,
遍历集合元素,验证重复元素是否过滤了;如果没有过滤,实现过滤功能;把每个小车的price降10000元,再遍历,查看price是否已改变
import java.util.HashSet; import java.util.Iterator; public class JuneThreePracticeTestThree { public static void main(String[] args) { HashSet hashSet = new HashSet(); JuneThreePracticeCar carOne = new JuneThreePracticeCar("老王",34.5); JuneThreePracticeCar carTwo = new JuneThreePracticeCar("老张",2700); JuneThreePracticeCar carThree = new JuneThreePracticeCar("隔壁小姑娘",3400); JuneThreePracticeCar carFour = new JuneThreePracticeCar("隔壁老阿姨",7800); JuneThreePracticeCar carFive = new JuneThreePracticeCar("东莞单身老阿姨",34390000); hashSet.add(carOne); hashSet.add(carTwo); hashSet.add(carThree); hashSet.add(carFour); hashSet.add(carFive); System.out.println(hashSet); Iterator iterator = hashSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } // 过滤价格 Iterator<JuneThreePracticeCar> iteratorOne = hashSet.iterator(); // 需要指定泛型否则下面无法使用 while (iteratorOne.hasNext()){ double price = iteratorOne.next().getPrice()-1000; System.out.println(price); } } } class JuneThreePracticeCar{ private String name; private double price; public JuneThreePracticeCar() { } public JuneThreePracticeCar(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "JuneThreePracticeCar{" + "name='" + name + '\'' + ", price=" + price + '}'; }
22: 定义一个Collection接口类型的变量,引用一个List集合的实现类,实现添加单个元素,添加另一个集合,删除元素,
判断集合中是否包含一个元素,判断是否为空,清除集合,返回集合里元素的个数等常用操作。
public static void main(String[] args) { List list = new ArrayList(); for (int i = 0; i < 6 ; i++) { list.add(i); } List listOne = new ArrayList(); listOne.add(34); listOne.add(45); list.addAll(listOne); System.out.println(list); list.remove(0); System.out.println(list.contains(76)); System.out.println(list.isEmpty()); list.clear(); System.out.println(list.size()); }
23:创建ArrayList实例化对象,添加10个以上的元素,在2号位插入一个元素,获得5号位元素,删除6号位元素,修改7号位的元素;
public static void main(String[] args) { ArrayList list = new ArrayList(); for (int i = 0; i < 11 ; i++) { list.add(i); } // 因为都是按照下标来的 所以号位都要减去1 list.add(1,"老王"); list.get(4); list.remove(5); list.set(6,"老张"); }
24:通过四种方法遍历上题中的集合
public static void main(String[] args) { ArrayList list = new ArrayList(); for (int i = 0; i < 11 ; i++) { list.add(i); } // 因为都是按照下标来的 所以号位都要减去1 list.add(1,"老王"); list.get(4); list.remove(5); list.set(6,"老张"); //四种方法遍历集合 // 方法一 foreach for (Object obj: list ) { System.out.println(obj); } //方法二 普通for循环 for (int i = 0; i < list.size() ; i++) { System.out.println(i); } //方法二迭代器 Iterator iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } //方法四 for (Iterator iter = list.iterator();iterator.hasNext();) { System.out.println(iter.next()); } }
25: 创建LinkedList实例化对象,练习具有队列特点的方法
创建LinkedList实例化对象,练习具有队列特点的方法
26: 按要求实现下列问题: 1)封装一个新闻类,包含标题和内容属性,提供get、set方法,重写toString方法,打印对象时只打印标题;(10分) 2)只提供一个带参数的构造器,实例化对象时,只初始化标题;并且实例化两个对象: 新闻一:中国多地遭雾霾笼罩空气质量再成热议话题 新闻二:春节临近北京“卖房热” 3)将新闻对象添加到ArrayList集合中,并且使用ListIterator倒序遍历; 4)在遍历集合过程中,对新闻标题进行处理,超过15字的只保留前14个,然后在后边加“…” 5)在控制台打印遍历出经过处理的新闻标题; 27: 定义一个Map接口类型的变量,引用一个实现类,添加键值对,判断集合中是否包含某一key值,通过某一key值得到value值,通过某一key删除键值对,
把另一个map集合添加到此map集合,判断是否为空,清除集合,返回集合里元素的个数等常用操作。
27:
HashMap hashMap = new HashMap(); HashMap hashMapOne = new HashMap(); hashMap.put(1,"老王"); hashMap.put(2,"老张"); hashMapOne.put(4,"隔壁小姐姐"); hashMapOne.put(6,"老张在隔壁"); System.out.println(hashMap.containsKey(1)); System.out.println(hashMap.get(2)); hashMap.remove(1); hashMap.putAll(hashMapOne); // 另一个hashMapOne集合添加到此hashMap集合 System.out.println(hashMapOne.isEmpty()); // 判断是否为空 hashMapOne.clear(); System.out.println(hashMap.size()); Set set = hashMap.keySet(); // 获取所有的key Collection list = hashMap.values(); // 获取所有的values Set setOne = hashMap.entrySet(); // 获取所有的entry
28 : 通过两种方法遍历上题中的map集合
for (Object entry: hashMap.entrySet() ) { System.out.println(entry); }
29:
使用Map接口的实现类完成员工工资(姓名--工资)的摸拟:
1)添加几条信息
2)列出所有的员工姓名
3列出所有员工姓名及其工资
4)删除名叫“Tom”的员工信息
5)输出Jack的工资,并将其工资加1000元(通过取值实现)
6)将所有工资低于1000元的员工的工资上涨20%(通过取值实现)
30:创建有序的map集合的实例化对象,添加元素,查看排序结果
public static void main(String[] args) { TreeMap treeMap = new TreeMap(); treeMap.put(1,"老王"); treeMap.put(4,"老张"); treeMap.put(2,"隔壁"); System.out.println(treeMap); //{1=老王, 2=隔壁, 4=老张} }
31:
封装一个新闻类,包含标题、作者、新闻内容和发布时间,新闻标题如下: 新闻一:中国多地遭雾霾笼罩空气质量再成热议话题 新闻二:民进党台北举行“火大游行” 新闻三:春节临近北京“卖房热” 新闻四:春节临近北京“卖房热” 完成如下要求(共50分,每小题10分): 1)完成对新闻类的设计,要求在初始化新闻类对象时 ,通过构造传参的形式对新闻标题赋值,并要求实例化四个对象,标题内容如题。 2)要求打印新闻对象时,直接打印新闻标题; 3)要求使用equals方法比较新闻时,只要标题相同,就认为是同一新闻,请输出新闻一与新闻二的比较结果,新闻三与新闻四的比较结果。 4)将新闻对象存入HashSet集合中,并且遍历集合,打印新闻类对象; 5)打印集合中新闻数量。
32:
使用HashMap类实例化一个Map类型的对象m1,键(String类型)和值(int型)分别用于存储员工的姓名和工资,存入数据如下: 张三——800元;李四——1500元;王五——3000元; 1)将张三的工资更改为2600元 2)为所有员工工资加薪100元; 3)遍历集合中所有的员工 4)遍历集合中所有的工资
33:
创建一个List集合的对象,添加几个数字,反转对象中元素的顺序;根据元素的自然顺序排序;
List list = new ArrayList(); list.add(1); list.add(897); list.add(65); list.add(34); Collections.reverse(list); // 反转 System.out.println(list); Collections.sort(list);// 排序 System.out.println(list);
34:
List listOne = new ArrayList(); listOne.add("老王"); listOne.add("隔壁老王"); listOne.add("老张"); System.out.println(listOne); Collections.reverse(listOne); System.out.println(listOne); Collections.sort(listOne); System.out.println(listOne);
35:
List listTwo = new ArrayList(); listTwo.add(1); listTwo.addAll(listOne); listTwo.addAll(list); System.out.println(listTwo); Collections.swap(listTwo,1,2); // 将listTwo集合内的下标为1和下标为2的交换位置 System.out.println(listTwo); System.out.println(Collections.max(list)); // 最大值 System.out.println(Collections.min(list)); // 最小值
按要求完成如下操作 1. 生成10个随机数,值在100到200之间; 2. 将这十个数存入HashSet集合中(有可能集合的长度小于10)。 3. 将这个HashSet集合转换成ArrayList集合 4. 重新为ArrayList集合排序,按照从小到大的顺序; 5. 使用foreach遍历集合; 按要求完成如下操作 1 )封装一个汽车类,包含String name、int speed属性,在测试类中实例化三个对象:c1,c2,c3,分别设置name为:“奥拓”,“宝马”,“奔驰”,速度分别设置为:100,200,300 2 )使用Map集合对象m1将这三个汽车类对象保存成key,然后将int型的汽车价钱作为值保存在m1的value中,上述三款汽车分别对应的价钱是10000,500000,2000000 3 )遍历m1的键,打印name属性 4 )通过合适的方法,求出m1中“宝马”的价格,并打印结果; 5 )经过折旧,所有汽车都降价到原来的80%,请打印降价后“宝马”的价格 按要求完成如下操作 1 ) 要求集合对象c1中,只能添加字符串形式的单个元素,元素可以重复,在测试类中为c1集合添加字符串“这是一个可以重复的集合”三遍,然后遍历打印结果。 2 )要求集合对象c2中只能添加整型数值,并且不可重复,按自然顺序排序。要求遍历集合对象,打印添加进1,2,3,4,5五个数字的c2集合 3 )要求创建一个合适的Map集合对象m1,它的键和值都只能是字符串,并且值可以是null,像map集合中添加三组字符串,其中一个只有键,值是空,遍历这个集合对象的键,并打印键。 4)想办法将m1中所有值为null都替换成一个字符串”这里是空值” 5)遍历m1的所有值。 以下代码的运行结果? public static void main(String[] args) { Integer[] datas = {1,2,3,4,5}; List<Integer> list = Arrays.asList(datas); list.add(5); System.out.println(list.size()); } 运行异常,不允许添加元素