进阶JAVA篇- Java 综合基本语法实践(习题一)
路漫漫其修远兮,吾将上下而求索。—— 屈原
目录
第三道题: 手写 ArrayList 集合(模拟实现 ArrayList 核心API)
第五道题:手写单链表(模拟实现 LinkedList 集合的核心API)
第一道题:集合的灵活运用
题目如下:
对题目进行分析:
可以根据囚犯的编号、所占的位置信息,可以封装成一个囚犯类,接着就是遍历 100 个人的信息了,推荐可以用 for 来遍历。这里要注意的是不能重复出现相同的编号,这里可以单独构造一个方法,去除重复的编号。对于删除奇数位置上的数据,那么新 new 一个集合来接收占位为偶数的元素就好了。这题不算难,可以根据题目自己试着敲一敲。
具体代码如下:(答案肯定是不唯一的,答案对了,还有逻辑清晰即可)
先定义了囚犯类:
public class People { private int number; private int location; public People(int number, int location) { this.number = number; this.location = location; } public People() { } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public int getLocation() { return location; } public void setLocation(int location) { this.location = location; } @Override public String toString() { return "People{" + "number=" + number + ", location=" + location + '}'; } }
import java.util.ArrayList; import java.util.List; import java.util.Random; public class Text { private static List<People> peopleLists = new ArrayList<>(); public static void main(String[] args) { Random random = new Random(); for (int i = 1; i <= 100 ; i++) { //先判断取到的数是否重复了 int number = random.nextInt(200)+1; if (isRepeat(number)){ i--; continue; }else{ People people = new People(number,i); peopleLists.add(people); } } System.out.println("原先的排位:"); System.out.println(peopleLists); //除去在位在奇数位置的人,直到剩最后一位。 //1,2,3,4,5,6,7,8 //0,1,2,3,4,5,6,7 //可以看出来就是要保留集合中的奇数位 while (peopleLists.size() > 1){ List<People> temp = new ArrayList<>(); for (int i = 1; i < peopleLists.size(); i+=2) { temp.add(peopleLists.get(i)); } peopleLists = temp; } System.out.println("后来的排位:"); System.out.println(peopleLists.get(0)); } private static boolean isRepeat(int number){ for (int i = 0; i < peopleLists.size(); i++) { if (peopleLists.get(i).getNumber() == number) { return true; } } return false; } }
第二道题:基础编程能力
题目如下:
对题目进行分析:
先定义出来 User 实体类,这里难点在于将 userStrs 变量进行拆分为一个个字符串,这里就可以使用 split() 方法了,用数组来接收,先拆分 "#",再用数组接收 ":"的字符串,就拆调用两次 split() 方法即可,接着就是对数据的类型处理了,其中两个难点就是字符串 id 转变为 long 类型,就直接用 Long.valueof() 方法就行了,还有一个是转变 LocalDay birthday ,用 LocalDay.parse() 来解析字符串。再有就是封装到 Map 集合中,对原来的 list 集合遍历,再需要用到的是 containsKey() 方法来判断是否重复存在了,最后可以将数据放到 map 集合中了。
具体代码如下:(答案肯定是不唯一的,答案对了,还有逻辑清晰即可)
import java.time.LocalDate; public class User { private Long id; private String gender; private LocalDate birthday; private String name; public User() { } public User(Long id, String gender, LocalDate birthday, String name) { this.id = id; this.gender = gender; this.birthday = birthday; this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public LocalDate getBirthday() { return birthday; } public void setBirthday(LocalDate birthday) { this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", gender='" + gender + '\'' + ", birthday=" + birthday + ", name='" + name + '\'' + '}'; } }
import java.time.LocalDate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Text { public static void main(String[] args) { List<User> userLists = new ArrayList<>(); String userStrs = "10001:张三:男:1990-01-01#" + "10002:李四:女:1989-01-09#" + "10003:王五:男:1999-09-09#" + "10004:刘备:男:1899-01-01#" + "10005:孙悟空:男:1900-01-01#" + "10006:张三:女:1999-01-01#" + "10007:刘备:女:1999-01-01#" + "10008:张三:女:2003-07-01#" + "10009:猪八戒:男:1900-01-01#"; String[] userInformation = userStrs.split("#"); for (int i = 0; i < userInformation.length; i++) { String[] userSpilt = userInformation[i].split(":"); String idString = userSpilt[0]; long id = Long.valueOf(idString); String name = userSpilt[1]; String gender = userSpilt[2]; String birthdayString = userSpilt[3]; LocalDate birthday = LocalDate.parse(birthdayString); User user = new User(id,gender,birthday,name); userLists.add(user); } System.out.println(userLists); //遍历集合中的每个名字出现的次数 Map<String,Integer> map = new HashMap<>(); for (User userList : userLists) { if (map.containsKey(userList.getName())){ map.put(userList.getName(),map.get(userList.getName())+1); }else { map.put(userList.getName(),1); } } //遍历打印map集合 map.forEach((k,v)-> System.out.println(k+" : "+v)); } }
第三道题: 手写 ArrayList 集合(模拟实现 ArrayList 核心API)
题目如下:
对题目进行分析:
ArrayList 添加第一个元素时集合默认的大小为数组空间为 10 ,每当等于或者超过相关的值,就会扩容为原来的1.5倍,一直往后下去。重点在于一开始类中应该得设置一个 size = 0 ,这个成员变量很重要,即是代表了元素的个数,还可以是指向下一个应该添加元素的位置。
具体代码如下:(答案肯定是不唯一的,答案对了,还有逻辑清晰即可)
public interface MyConsumer<E> { void accept(E e); }
import java.util.Arrays; public class MyArrayList <E>{ private int defaultLength = 10; private Object[] arr = new Object[defaultLength]; private int size = 0; public MyArrayList() { } //添加数据 public boolean add(E e){ //先判断arr数组是否要扩容 if (isExpansion()){ //已经扩容成功 System.out.println("已经扩容了"); } arr[size++] = e; return true; } //查询数据 public E get(int index){ if(index >= size || index < 0){ throw new RuntimeException(); } else { return (E)arr[index]; } } //删除数据 public E remove(int index) { if (index >= size || index < 0) { throw new RuntimeException(); } else { E retainData = (E) arr[index]; if (index != size - 1) { //1,2,3,4,5,6 //0,1,2,3,4,5 //int remainder = size - index - 1; for (int i = index; i < size - 1; i++) { arr[i] = arr[i + 1]; } } size--; return retainData; } } //获取集合大小size public int size(){ return size; } //开发一个forEach方法 public void forEach(MyConsumer myConsumer){ for (int i = 0; i < size; i++) { myConsumer.accept(arr[i]); } } private boolean isExpansion(){ if (size >= defaultLength){ defaultLength = (int) (defaultLength * (1.5)); Object[] temp = new Object[defaultLength]; for (int i = 0; i < size; i++) { temp[i] = arr[i]; } arr = temp; return true; }else { return false; } } @Override public String toString() { Object[] temp = new Object[size]; for (int i = 0; i < size; i++) { temp[i] = arr[i]; } return Arrays.toString(temp); } }
public class Text { public static void main(String[] args) { MyArrayList<String> myArrayList = new MyArrayList<>(); myArrayList.add("1"); myArrayList.add("2"); myArrayList.add("3"); myArrayList.add("4"); myArrayList.add("5"); myArrayList.add("6"); myArrayList.add("7"); myArrayList.add("8"); myArrayList.add("9"); myArrayList.add("10"); myArrayList.add("11"); myArrayList.add("13"); myArrayList.add("13"); myArrayList.add("19"); myArrayList.add("13"); myArrayList.add("18"); System.out.println(myArrayList); System.out.println("------------------"); System.out.println(myArrayList.get(2)); System.out.println("------------------"); System.out.println(myArrayList.remove(3)); System.out.println("删除的结果:"+myArrayList); System.out.println(myArrayList.size()); System.out.println("---------遍历---------"); myArrayList.forEach(System.out::println); } }
第四道题:二分查找的应用
题目如下:
对题目进行分析:
这里注明了必须是确保程序的时间复杂度是 O(log2n),很显然就是要使用二分法来进行查找元素,用二分法来寻找目标元素的开始位置还有结束位置,那就可以用分别使用二分法来寻找开始位置还有结束位置,注意的是,若数组中不存在目标元素的话,就要返回-1。
具体代码如下:(答案肯定是不唯一的,答案对了,还有逻辑清晰即可)
import java.util.Arrays; public class BinaryLookup { public static void main(String[] args) { int[] arr = {7,7,7,8,8,8,10}; int target = 9; int[] a = lookupRightAndLeft(arr,target); System.out.println(Arrays.toString(a)); } public static int lookupLeft(int[] arr, int target){ int left = 0; int right = arr.length-1; int isLeft = - 1; while (left <= right){ int index = (left+right)/2; if ( arr[index] == target){ isLeft = index; right = index - 1; } else if (arr[index] > target) { right = index - 1; }else { left = index + 1; } } return isLeft; } public static int lookupRight(int[] arr, int target){ int left = 0; int right = arr.length-1; int isRight = - 1; while (left <= right){ int index = (left+right)/2; if ( arr[index] == target){ isRight = index; left = index + 1; } else if (arr[index] > target) { right = index - 1; }else { left = index + 1; } } return isRight; } public static int[] lookupRightAndLeft(int[] arr,int target){ int[] returnArr = new int[2]; int isLeft = lookupLeft(arr,target); int isRight = lookupRight(arr,target); returnArr[0] = isLeft; returnArr[1] = isRight; return returnArr; } }
第五道题:手写单链表(模拟实现 LinkedList 集合的核心API)
题目如下:
对题目进行分析:
由于官方的 LinkedList 集合使用了内部类来实现的,所以为了保持一致,我们也使用内部类来模拟实现,单链表需要一个个节点来组成,因此,定义一个内部类来封装节点,节点无非就是数据还有该类型对象的引用,需要注意的是,这里需要设置泛型类,我感觉用以上的题目给的信息来实现 LinkedList 集合与原 LinkedList 集合差别会很大而且很乱,所以我做了一些改进。
具体代码如下:(答案肯定是不唯一的,答案对了,还有逻辑清晰即可)
public interface MyConsumer<E> { void accept(E e); }
public class MyLinkedList<E> { private int size = 0; private NodeCode hand; class NodeCode{ E data; NodeCode nextNodeCode; public NodeCode(E data, NodeCode nextNodeCode) { this.data = data; this.nextNodeCode = nextNodeCode; } } public NodeCode add(E e){ if (hand == null){ hand = new NodeCode(e,null); }else { NodeCode temp = hand; while (temp.nextNodeCode != null){ temp = temp.nextNodeCode; } temp.nextNodeCode = new NodeCode(e,null); } size++; return hand; } public void forEach(MyConsumer<E> myConsumer){ NodeCode first = hand; while ( first!=null ){ myConsumer.accept(first.data); first = first.nextNodeCode; } } public void reverse(int left,int right){ NodeCode first = hand; int count = 1; NodeCode tempLeft = null; Object[] arr = new Object[right-left + 1]; while (count <= right){ if (count == left){ tempLeft = first; } if (count >= left ) { arr[count-left] = first.data; } first = first.nextNodeCode; count++; /* if (count == right){ arr[count-left] = first.data; }*/ } for (int i = arr.length - 1; i >= 0; i--) { tempLeft.data = (E) arr[i]; tempLeft = tempLeft.nextNodeCode; } } }
public class Text { public static void main(String[] args) { MyLinkedList<Integer> myLinkedList = new MyLinkedList<>(); myLinkedList.add(1); myLinkedList.add(2); myLinkedList.add(3); myLinkedList.add(4); myLinkedList.add(5); myLinkedList.add(6); myLinkedList.reverse(2,5); myLinkedList.forEach(new MyConsumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } }); /* MyLinkedList<String> myLinkedList = new MyLinkedList<>(); myLinkedList.add("1"); myLinkedList.add("2"); myLinkedList.add("3"); myLinkedList.add("4"); myLinkedList.add("5"); myLinkedList.add("5"); myLinkedList.add("6"); myLinkedList.add("6"); myLinkedList.forEach(System.out::println);*/ /* System.out.println("-----------------"); LinkedList<String> list = new LinkedList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("5"); list.add("6"); list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } });*/ } }
若可以完成大部分题目,很高心衷心地祝贺你,你的编程能力是极高的!!!
想要进一步了解更多的相关 Java 知识,可以点击以下链接:小扳_-CSDN博客