I am trying to all possible child domains from a given host. I have written following code. It works but my only worry is performance.
Is it required to optimize this code further:
import java.util.Arrays;
import java.util.Collections;
public class DemoExtractHostArray {
public static String[] createHostArray(String host) {
String[] stringArr = host.split("\\.");
String[] hostArray = new String[stringArr.length];
int hostIndex = 0;
for(int index = stringArr.length-1; index>=0;index--){
if(hostIndex==0){
hostArray[hostIndex] = stringArr[index];
}
else{
hostArray[hostIndex] = stringArr[index]+"."+hostArray[hostIndex-1];
}
hostIndex++;
}
Collections.reverse(Arrays.asList(hostArray));
return hostArray;
}
public static void main(String a[]){
for(String s: createHostArray("a.b.c.d.e.f")){
System.out.println(s);
}
}
}
Output:
a.b.c.d.e.f
b.c.d.e.f
c.d.e.f
d.e.f
e.f
f
The only potential improvement to your code is removing this call:
Collections.reverse(Arrays.asList(hostArray));
Since you are creating the hostArray and then reversing it, you might as well change the loop to create the array in reverse order right away, so as to no longer requiring an explicit reversal:
// hostIndex is no longer required - remove the line below:
// int hostIndex = 0;
for(int index = stringArr.length-1 ; index>=0 ; index--){
if(index == stringArr.length-1) {
hostArray[index] = stringArr[index];
}
else{
hostArray[index] = stringArr[index]+"."+hostArray[index+1];
}
}
I would personally use recusion. This implementation does not require the reversal of the array and, in my opinion, may be easier to follow.
http://ideone.com/MnMZOL
package com.poachit.utility.web;
import java.util.Arrays;
import java.util.Collections;
public class DemoExtractHostArray {
public static void createHostArray(String[] root, String[] result, int index) {
String host="";
int i = index;
if (index == root.length) {
return;
}
for ( ; i < root.length-1; i++) {
host += root[i] + ".";
}
if (i < root.length) {
host += root[i];
}
result[index] = host;
createHostArray(root, result, ++index);
}
public static void main (String[] args) throws java.lang.Exception
{
String host = "a.b.c.d.e.f";
String [] tokens = host.split("\\.");
String [] result = new String[tokens.length];
createHostArray(tokens, result, 0);
for (String s : result) {
System.out.println(s);
}
}
}
You can optimize the code like this
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Test {
public static String[] createHostArray(String host) {
String[] stringArr = host.split("\\.");
String[] hostArray = new String[stringArr.length];
int hostIndex = 0;
for(int index = stringArr.length-1; index>=0;index--){
if(hostIndex==0){
hostArray[hostIndex] = stringArr[index];
}
else{
hostArray[hostIndex] = stringArr[index]+"."+hostArray[hostIndex-1];
}
hostIndex++;
}
Collections.reverse(Arrays.asList(hostArray));
return hostArray;
}
public static String[] betterCreateHostArray(String host) {
List<String> hostList = new ArrayList<String>();
do {
if(!host.contains(".")) {
hostList.add(host);
break;
} else {
hostList.add(host);
host = host.substring(host.indexOf('.')+1);
}
} while(host.length() > 0);
return hostList.toArray(new String[hostList.size()]);
}
public static void main(String a[]){
long startTime = System.nanoTime();
String[] array = createHostArray("a.b.c.d.e.f");
long endTime = System.nanoTime();
long timeByFirstApproach = endTime - startTime;
for(String s: array){
System.out.println(s);
}
System.out.println("=====");
startTime = System.nanoTime();
array = betterCreateHostArray("a.b.c.d.e.f");
endTime = System.nanoTime();
long timeBySecondApproach = endTime - startTime;
for(String s: array){
System.out.println(s);
}
System.out.println(String.format("Time taken by first approach=[%d] nano seconds and\n"
+ "Time taken by second approach=[%d] nano seconds", timeByFirstApproach,timeBySecondApproach));
}
}
and here the performance result
a.b.c.d.e.f
b.c.d.e.f
c.d.e.f
d.e.f
e.f
f
=====
a.b.c.d.e.f
b.c.d.e.f
c.d.e.f
d.e.f
e.f
f
Time taken by first approach=[1625572] nano seconds and
Time taken by second approach=[308289] nano seconds
Second approach is more than 5 times faster than the approach you are following.
Related
I have an array called myArray that contains words separated by a space and trimmed from a PDF from the first page to the last page. I wrote a simple print array method that iterates through and prints each element one by one and it looks great!
Immediately after I have it go through another for loop for the length of the array and checks if (myArray[i].equals("(19)")) {//print something} When printing the array to the console it is clear that the value (19) exists in the array.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import org.apache.pdfbox.cos.COSDocument;
import org.apache.pdfbox.io.RandomAccessRead;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
public class Main {
static File file;
static PDFTextStripper textStripper;
static PDDocument pdDoc;
static COSDocument cosDoc;
static String parsedText;
static int sum = 0;
static String[] myArray;
static String[] events = {"400", "800", "1500",
"3000", "5000", "10000"};
public static void main(String[] args) {
//Read the PDF file into instance variable file
readFile();
try {
parsePDF(file);
} catch (IOException e) {
e.printStackTrace();
}
myArray = parsedText.split(" ");
removeWhiteSpace(myArray);
printArray(myArray);
//System.out.println();
String currentEvent = "";
for (int i = 0; i < myArray.length; i++) {
if (contains(myArray[i])) {
currentEvent = myArray[i];
}
if (!currentEvent.equals("")) {
if (myArray[i].charAt(0) == '(' && (myArray[i].charAt(myArray[i].length() - 1) == ')')) {
String formatedRunners = "";
//It is possible to see some numbers such as (19)) or (19)
if (containsCharacter(myArray[i], ')') == 2) {
formatedRunners = myArray[i].substring(1, myArray[i].length() - 2);
} else {
formatedRunners = myArray[i].substring(1, myArray[i].length() - 1);
}
int numberOfRunners = Integer.parseInt(formatedRunners);
int distance = Integer.parseInt(currentEvent);
sum += numberOfRunners * distance;
//reset currentEvent
currentEvent = "";
}
}
}
//Print total distance in meters
System.out.println(sum + " meters");
//Convert meters to miles using the following equation: meters / 1609.344
System.out.println( Math.round((sum / 1609.344)) + " miles");
}
public static void readFile() {
Scanner c = new Scanner(System.in);
System.out.println("Enter a file path: ");
String filePath = c.nextLine();
file = new File(filePath);
}
public static void parsePDF(File file) throws IOException {
textStripper = new PDFTextStripper();
pdDoc = PDDocument.load(file);
//Parse PDF
textStripper.setStartPage(1);
//textStripper.setEndPage();
//Parsed String
parsedText = textStripper.getText(pdDoc);
}
public static boolean contains(String s) {
for (int i = 0; i < events.length; i++) {
if (s.equals(events[i])) {
return true;
}
}
return false;
}
public static void printArray(String[] a) {
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
public static void removeWhiteSpace(String[] a) {
for (int i = 0; i < myArray.length; i++) {
if (myArray[i].equals("")) {
//Use some filler to avoid crashes when checking characters
myArray[i] = "NULL";
}
//Trim off all extra whitespace
myArray[i] = myArray[i].trim();
}
}
public static int containsCharacter(String str, char c) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == c) {
count++;
}
}
return count;
}
}
Here is what I want:
Parsing and trimming etc. (OK)
Iterating over myArray (in the main method) and detecting events (OK)
If an event occurred then the next value must be (Any number) like (19)
(NOK)
The number from step 3. will be used to compute another number
Reset the current event to repeat the process over and
over again.
It seems like that it is reading each event correctly but only picks up (19)) instead of (19).
There are several problems in you code (No Exceptionhandling, everything static, small bugs etc.) but I will focus on the major issue. (I removed the code which I did not change)
public class Main {
static File file;
static PDFTextStripper textStripper;
static PDDocument pdDoc;
static COSDocument cosDoc;
static String parsedText;
static int sum = 0;
static String[] myArray = {"Seeded", "3000", "random", 25, "(44)", "1500", "random", "(13)"};
static String[] events = {"400", "800", "1500", "3000", "5000", "10000", "200.000"};
public static void main(String[] args) {
//Read the PDF file into instance variable file
readFile();
try {
parsePDF(file);
} catch (IOException e) {
e.printStackTrace();
}
myArray = parsedText.split(" ");
removeWhiteSpace(myArray);
String currentEvent = "";
for (int i = 0; i < myArray.length; i++) {
if (contains(myArray[i])) {
currentEvent = myArray[i];
}
else if (!currentEvent.isEmpty()) {
Integer value = extractNumber(myArray[i]);
if (!myArray[i].isEmpty() && value!=null) {
int distance = Integer.parseInt(currentEvent);
sum += value.intValue() * distance;
//reset currentEvent
currentEvent = "";
}
}
}
//Print total distance in meters
System.out.println(sum + " meters");
//Convert meters to miles using the following equation: meters / 1609.344
System.out.println( Math.round((sum / 1609.344)) + " miles");
}
public static Integer extractNumber(String toCheck) {
Pattern r = Pattern.compile("^.*?\\([^\\d]*(\\d+)[^\\d]*\\).*$");
Matcher m = r.matcher(toCheck);
if(m.find()) {
return Integer.valueOf(m.group(1));
}
return null;
}
public static void removeWhiteSpace(String[] a) {
for (int i = 0; i < myArray.length; i++) {
//Trim off all extra whitespace
myArray[i] = myArray[i].trim();
}
}
The result is
151500 meters
94 miles
Algorithm asked in one of the top company's interview, but I am not able to find a feasible solution. Need expert advice.
Suppose a student wants to attend maximum number of classes in a collage in a day (without any class overlap).
Input Format
The first line contains an integer n which gives the number of subjects offered on that day.
The next n lines follow containing the subject name (which is a string) followed by the start and end time for that subject in 24-hour format: hh:mm
For eg: Maths 10:00 11:00
Note: The timings are given in a 24-hour format and the subject names do not have spaces between them.
Output Format
The output should contain a number representing the maximum number of classes the student can choose.
Constraints
2 <= n <= 100
start time of a class < end time of class
Sample Input
4
Maths 16:00 18:00
ComputerScience 12:00 13:00
Physics 12:30 14:00
Chemistry 14:00 16:30
Sample Output
2
Explanation
ComputerScience starts the earliest and ends the earliest, so we take it first. After that, we cannot take Physics because it starts before ComputerScience is over. So we will take the next class, that is, Chemistry. But after Chemistry we cannot take Maths as Maths class starts before Chemistry class ends. So we can schedule a maximum of 2 classes for the day.
Below is my solution but I am not getting correct answer:
private void getMaxClass(String input) {
Map<String, Long> classTime = new LinkedHashMap<>();
Map<String, List<String>> timeMap = new LinkedHashMap<>();
String[] split = input.split(" ");
String subject = split[0];
String StartTime = split[1];
String endTime = split[2];
List<String> lvalue = new ArrayList<>();
lvalue.add(StartTime);
lvalue.add(endTime);
timeMap.put(subject, lvalue);
long difference = FineDifferenceInTime(StartTime, endTime);
classTime.put(subject, difference);
int count = 0;
Date date1 = null;
Date date2 = null;
Map<String, Long> sortedByValueDesc = classTime.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
for (Map.Entry<String, Long> entry : sortedByValueDesc.entrySet()) {
String sub = entry.getKey();
List<String> startEnd = timeMap.get(sub);
Date dateBefore = null;
Date dateAfter = null;
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
try {
dateBefore = format.parse(startEnd.get(0));
dateAfter = format.parse(startEnd.get(1));
} catch (ParseException e) {
e.printStackTrace();
}
if (count == 0) {
count++;
try {
date1 = format.parse(startEnd.get(0));
date2 = format.parse(startEnd.get(1));
} catch (ParseException e) {
e.printStackTrace();
}
}
if (dateBefore.after(date1) && dateBefore.before(date2)) {
timeMap.remove(sub);
}
}
System.out.println(timeMap.size());
}
This is known in literature as the Interval Scheduling Problem. There are many ways to solve it, but since it is NP-complete (as there is a a polynomial reduction from VC) you'll necessarily need to explore all the combinations.
Greedy algorithms do exist (as is yours and the solution by #PriyankaDeshmukh), but they don't guarantee you the exact solution for all instances of the problem.
The solution below is a simple tree search: at each level we decide if we take a given course or not and move on to decide on the next course.
You could also implement a dynamic programming solution.
Here is a very good blog post covering solutions to the Interval Scheduling Problem.
I modelled a student class the following way:
class StudentClass {
public int _start;
public int _end;
public String _name;
public StudentClass(String name, int start, int end) {
_name = name;
_start = start;
_end = end;
}
public boolean overlapsWith(StudentClass other) {
return _start < other._end && _end > other._start;
}
public String toString() {
return "[" + _start + " - " + _end + "] " + _name;
}
}
There are classes to represent the time of the day, but their syntax/instantiation is a bit annoying/verbose -- feel free to improve this answer though! My Java is also very rusty, so feel free to correct me :-)
The Schedule class has a getMaxSchedule() which returns the solution to the problem -- what is the maximum number of classes a student can take, such that none of them overlap?
There are a few ways to optimize it, but I left it as-is as I believe it's easier to be understood.
public class Schedule {
List<StudentClass> _classes = new LinkedList<>();
public void addClass(String name, int startTime, int endTime) {
_classes.add(new StudentClass(name, startTime, endTime));
}
private int getMaxSchedule(int index, Collection<StudentClass> selected) {
// check if we reached the end of the array
if (index >= _classes.size()) {
return 0;
}
StudentClass current = _classes.get(index);
// check if taking this class doesn't conflict with the
// previously-selected set of classes
boolean canTakeThisClass = true;
for (StudentClass other : selected) {
if (current.overlapsWith(other)) {
canTakeThisClass = false;
break;
}
}
// check best schedule if we don't take this class
int best = getMaxSchedule(index + 1, selected);
// check best schedule if we take this class (if such is possible)
if (canTakeThisClass) {
selected.add(current);
best = Math.max(best, 1 + getMaxSchedule(index + 1, selected));
selected.remove(current);
}
return best;
}
public int getMaxSchedule() {
Collection<StudentClass> selected = new ArrayList<>();
return getMaxSchedule(0, selected);
}
}
You can see the result is 3 for your concrete problem through the following:
public static void main(String[] args) {
Schedule s = new Schedule();
s.addClass("Maths", 1600, 1800);
s.addClass("Computer Science", 1200, 1300);
s.addClass("Physics", 1230, 1400);
s.addClass("Chemistry", 1400, 1630);
System.out.println("maximum classes: " + s.getMaxSchedule());
}
I tried it with Python. It gives correct output.
I got it sorted by start time of class.
sorted_by_start = [{'sub': 'ComputerScience', 'start': '12:00', 'end': '13:00',
'duration': 60}, {'sub': 'Physics', 'start': '12:30', 'end': '14:00', 'duration':
90}, {'sub': 'Chemistry', 'start': '14:00', 'end': '16:30', 'duration': 150},
{'sub': 'Maths', 'start': '16:00', 'end': '18:00', 'duration': 120}]
possible_sub = set()
for a, b in itertools.combinations(sorted_by_start, 2):
strt_tme = datetime.datetime.strptime(a["end"], '%H:%M')
end_tme = datetime.datetime.strptime(b["start"], '%H:%M')
if(strt_tme <= end_tme) :
possible_sub.add((a["sub"],b["sub"]))
print("A student can attend these combinations of subject classes:",possible_sub)
print("Maximum classes student can attend in a day is: ",max(map(len,possible_sub)))
Here trick part is deciding how many combinations you can make. So, that you can do by adding additional for loop ranging from 2 to length of sorted_list and pass i to combinations(sorted_list, i) like this.
Ouput is :
A student can attend these combinations of subject classes: {('Physics', 'Maths'), ('Physics', 'Chemistry'), ('ComputerScience', 'Chemistry'), ('Compu
terScience', 'Maths')}
Maximum classes student can attend in a day is: 2
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class InputSubject implements Comparable<InputSubject>{
String subject;
String startTime;
String endTime;
InputSubject(){
}
InputSubject(String subject, String startTime, String endTime){
this.subject = subject;
this.startTime = startTime;
this.endTime = endTime;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
#Override
public int compareTo(InputSubject o) {
return this.endTime.compareTo(o.endTime);
}
}
public class SubjectSort {
static int getToatlSubject(List<InputSubject> list){
String sTime = null;
String eTime = null;
int count = 0;
int noOfSubject = 0;
for(InputSubject object : list){
if(count == 0){
count++;
eTime = object.getEndTime();
noOfSubject ++;
}
else {
if(object.getStartTime().compareTo(eTime) > 0){
eTime = object.getEndTime();
noOfSubject ++;
}
}
}
return noOfSubject;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
int days = Integer.parseInt(reader.readLine());
for(int i = 0 ; i < days ;i++){
int sub = Integer.parseInt(reader.readLine());
List<InputSubject> list = new ArrayList<>();
for(int k = 0 ; k < sub ; k++){
InputSubject inputSubject = null;
String subDetails = reader.readLine();
String[] subAndTimes = subDetails.split(" ");
inputSubject = new InputSubject(subAndTimes[0],subAndTimes[1],subAndTimes[2]);
list.add(inputSubject);
}
Collections.sort(list);
System.out.println(getToatlSubject(list));
}
} catch (Exception e) {
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class InputSubject implements Comparable<InputSubject>{
String subject;
String startTime;
String endTime;
InputSubject(){
}
InputSubject(String subject, String startTime, String endTime){
this.subject = subject;
this.startTime = startTime;
this.endTime = endTime;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
#Override
public int compareTo(InputSubject o) {
return this.endTime.compareTo(o.endTime);
}
}
public class solution {
static int getToatlSubject(List<InputSubject> list){
String sTime = null;
String eTime = null;
int count = 0;
int noOfSubject = 0;
for(InputSubject object : list){
if(count == 0){
count++;
eTime = object.getEndTime();
noOfSubject ++;
}
else {
if(object.getStartTime().compareTo(eTime) >= 0){
eTime = object.getEndTime();
noOfSubject ++;
}
}
}
return noOfSubject;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
int days = Integer.parseInt(reader.readLine());
for(int i = 0 ; i < days ;i++){
int sub = Integer.parseInt(reader.readLine());
List<InputSubject> list = new ArrayList<>();
for(int k = 0 ; k < sub ; k++){
InputSubject inputSubject = null;
String subDetails = reader.readLine();
String[] subAndTimes = subDetails.split(" ");
inputSubject = new InputSubject(subAndTimes[0],subAndTimes[1],subAndTimes[2]);
list.add(inputSubject);
}
Collections.sort(list);
System.out.println(getToatlSubject(list));
}
} catch (Exception e) {
}
}
}
i had same question in a coding round of a recruitment and I have solved it the following way and it gives correct answer. But unfortunately this code passed only 1 test case given in the challenge. I believe that the test cases were incorrect. Can anyone point out if I have missed something in code which might have led to this code failing other test cases?
import java.util.*;
import java.time.*;
import java.time.format.DateTimeFormatter;
import static java.time.temporal.ChronoUnit.*;
class solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
int n=sc.nextInt();
String trash=sc.nextLine();
HashMap subjects=new HashMap<String,String>();
HashMap starttime=new HashMap<String,LocalTime>();
HashMap endtime=new HashMap<String,LocalTime>();
HashMap length=new HashMap<String,Long>();
for (int j = 0; j < n; j++){
String classes = sc.nextLine();
String[] classesArray=classes.split(" ");
String subject=classesArray[0];
if(classesArray[1].split(":")[0].length()==1){
classesArray[1]="0"+classesArray[1];
}
if(classesArray[2].split(":")[0].length()==1){
classesArray[2]="0"+classesArray[2];
}
LocalTime startTime=LocalTime.parse(classesArray[1]);
LocalTime endTime=LocalTime.parse(classesArray[2]);
DateTimeFormatter formatter = DateTimeFormatter.ISO_TIME;
Long lengthLecture=MINUTES.between(startTime, endTime);
subjects.put(subject,subject);
starttime.put(subject,startTime);
endtime.put(subject,endTime);
length.put(subject,lengthLecture);
String value = startTime.format(formatter);
String value1 = endTime.format(formatter);
// System.out.printf("Sub:%s st:%s et:%s length:%d\n",subject,value,value1,lengthLecture);
}
findMax(subjects,starttime,endtime,length);
//System.out.println(num);
}
}
public static void findMax(HashMap<String,String> subs,HashMap<String,LocalTime> strt,HashMap<String,LocalTime> endt,HashMap<String,Long> length){
int number=0;
List<Integer> list = new ArrayList<Integer>();
String curr,next1;
for (Map.Entry<String,String> entry : subs.entrySet()){
//System.out.println("Checkign for number: "+entry.getKey());
number=findnext(entry.getKey(),strt,endt);
// System.out.println("Number is: "+number);
list.add(number);
}
System.out.println(Collections.max(list));
}
public static int findnext(String subjt,HashMap<String,LocalTime> strt,HashMap<String,LocalTime> endt){
String sub=subjt;
int number=1;
LocalTime substtime=strt.get(subjt);
LocalTime subedtime=endt.get(subjt);
Long timetillstart=922337203L;
for (Map.Entry<String,LocalTime> entry : strt.entrySet()){
if((entry.getValue().compareTo(subedtime)>=0) && (MINUTES.between(subedtime, entry.getValue())<=timetillstart)){
sub=entry.getKey();
substtime=strt.get(entry.getKey());
timetillstart=MINUTES.between(subedtime, entry.getValue());
}
}
if(sub!=subjt){
number=number+findnext(sub,strt,endt);
}
return number;
}
}
How to modify this program to print just three lines and intent to 2nd and 3rd start with space. My if-statement doesn't seem work
package com.TnationChallange;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
for (String part : getParts("screen space to display information", 7, 3)) {
System.out.println(part);
}
}
private static List<String> getParts(String string, int partitionSize, int maxLine) {
List<String> parts = new ArrayList<String>();
int len = string.length();
for (int i = 0; i < len; i += partitionSize) {
parts.add(string.substring(i, Math.min(len, i + partitionSize)));
maxLine++;
if (maxLine == 3) {
break;
}
}
return parts;
}
}
The third parameter you pass to the getParts method is 3 and because you call maxLine++ before if (maxLine == 3) that condition will never be true.
You should use something like this:
....
maxLines--;
if(maxLines == 0){
....
}
.....
You need a different variable to count the lines.
package com.TnationChallange;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
for (String part : getParts("screen space to display information", 7, 3)) {
System.out.println(part);
}
}
private static List<String> getParts(String string, int partitionSize, int maxLine) {
List<String> parts = new ArrayList<String>();
int len = string.length();
int count = 0;
for (int i = 0; i < len; i += partitionSize) {
parts.add(string.substring(i, Math.min(len, i + partitionSize)));
count++;
if (maxLine == count) {
break;
}
}
return parts;
}
}
This is assuming you want to limit your result by maxLine.
I have a continuous running thread in my application, which consists of a HashSet to store all the symbols inside the application. As per the design at the time it was written, inside the thread's while true condition it will iterate the HashSet continuously, and update the database for all the symbols contained inside HashSet.
The maximum number of symbols that might be present inside the HashSet will be around 6000. I don't want to update the DB with all the 6000 symbols at once, but divide this HashSet into different subsets of 500 each (12 sets) and execute each subset individually and have a thread sleep after each subset for 15 minutes, so that I can reduce the pressure on the database.
This is my code (sample code snippet)
How can I partition a set into smaller subsets and process (I have seen the examples for partitioning ArrayList, TreeSet, but didn't find any example related to HashSet)
package com.ubsc.rewji.threads;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
public class TaskerThread extends Thread {
private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
String symbols[] = new String[] { "One", "Two", "Three", "Four" };
Set<String> allSymbolsSet = Collections
.synchronizedSet(new HashSet<String>(Arrays.asList(symbols)));
public void addsymbols(String commaDelimSymbolsList) {
if (commaDelimSymbolsList != null) {
String[] symAr = commaDelimSymbolsList.split(",");
for (int i = 0; i < symAr.length; i++) {
priorityBlocking.add(symAr[i]);
}
}
}
public void run() {
while (true) {
try {
while (priorityBlocking.peek() != null) {
String symbol = priorityBlocking.poll();
allSymbolsSet.add(symbol);
}
Iterator<String> ite = allSymbolsSet.iterator();
System.out.println("=======================");
while (ite.hasNext()) {
String symbol = ite.next();
if (symbol != null && symbol.trim().length() > 0) {
try {
updateDB(symbol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateDB(String symbol) {
System.out.println("THE SYMBOL BEING UPDATED IS" + " " + symbol);
}
public static void main(String args[]) {
TaskerThread taskThread = new TaskerThread();
taskThread.start();
String commaDelimSymbolsList = "ONVO,HJI,HYU,SD,F,SDF,ASA,TRET,TRE,JHG,RWE,XCX,WQE,KLJK,XCZ";
taskThread.addsymbols(commaDelimSymbolsList);
}
}
With Guava:
for (List<String> partition : Iterables.partition(yourSet, 500)) {
// ... handle partition ...
}
Or Apache Commons:
for (List<String> partition : ListUtils.partition(yourList, 500)) {
// ... handle partition ...
}
Do something like
private static final int PARTITIONS_COUNT = 12;
List<Set<Type>> theSets = new ArrayList<Set<Type>>(PARTITIONS_COUNT);
for (int i = 0; i < PARTITIONS_COUNT; i++) {
theSets.add(new HashSet<Type>());
}
int index = 0;
for (Type object : originalSet) {
theSets.get(index++ % PARTITIONS_COUNT).add(object);
}
Now you have partitioned the originalSet into 12 other HashSets.
We can use the following approach to divide a Set.
We will get the output as
[a, b]
[c, d]
[e]`
private static List<Set<String>> partitionSet(Set<String> set, int partitionSize)
{
List<Set<String>> list = new ArrayList<>();
int setSize = set.size();
Iterator iterator = set.iterator();
while(iterator.hasNext())
{
Set newSet = new HashSet();
for(int j = 0; j < partitionSize && iterator.hasNext(); j++)
{
String s = (String)iterator.next();
newSet.add(s);
}
list.add(newSet);
}
return list;
}
public static void main(String[] args)
{
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
int size = 2;
List<Set<String>> list = partitionSet(set, 2);
for(int i = 0; i < list.size(); i++)
{
Set<String> s = list.get(i);
System.out.println(s);
}
}
If you are not worried much about space complexity, you can do like this in a clean way :
List<List<T>> partitionList = Lists.partition(new ArrayList<>(inputSet), PARTITION_SIZE);
List<Set<T>> partitionSet = partitionList.stream().map((Function<List<T>, HashSet>) HashSet::new).collect(Collectors.toList());
The Guava solution from #Andrey_chaschev seems the best, but in case it is not possible to use it, I believe the following would help
public static List<Set<String>> partition(Set<String> set, int chunk) {
if(set == null || set.isEmpty() || chunk < 1)
return new ArrayList<>();
List<Set<String>> partitionedList = new ArrayList<>();
double loopsize = Math.ceil((double) set.size() / (double) chunk);
for(int i =0; i < loopsize; i++) {
partitionedList.add(set.stream().skip((long)i * chunk).limit(chunk).collect(Collectors.toSet()));
}
return partitionedList;
}
A very simple way for your actual problem would be to change your code as follows:
Iterator<String> ite = allSymbolsSet.iterator();
System.out.println("=======================");
int i = 500;
while ((--i > 0) && ite.hasNext()) {
A general method would be to use the iterator to take the elements out one by one in a simple loop:
int i = 500;
while ((--i > 0) && ite.hasNext()) {
sublist.add(ite.next());
ite.remove();
}
I'm new here..
I want to make a code to remember the last 10 numbers and to be not same.
private static ArrayList<Integer> nums = new ArrayList<Integer>();
public static void main(String[] args)
{
System.out.println(getRandomNumber());
}
public static int getRandomNumber()
{
int randomN = 0, rand = Rnd.nextInt(20);
while (nums.size() == 10)
{
nums.remove(nums.get(0));
continue;
}
if (!nums.contains(rand))
{
nums.add(rand);
randomN = rand;
}
else getRandomNumber();
return randomN;
}
when the array reach 10 values the first one will be deleted .. I hope you understand what I want :) Thanks
Try using an ArrayDequeue and when the length grows to more than 10, you simple remove the items from the tail.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
class main{
public ArrayList<Integer> nums;
public Random generator;
public static void main(String[] args){
// Calling Start
(new main()).start();
}
public void start(){
nums = nums = new ArrayList<Integer>();
generator = new Random();
for(int i=0;i<15;i++){
add(generator.nextInt(20));
print();
}
}
public void add(int newNumber){
// Check by iterating if i is already in nums
Iterator it = nums.iterator();
while(it.hasNext()){
if(newNumber == (Integer) it.next())
return; // i is already in our list
// so get out add()
}
if(nums.size() == 10){
int forward = nums.get(0);
for(int i = 1; i < 10; i++){
// Move numbers back 1 position
nums.set(i-1,forward);
// Save next number in forward
forward = nums.get(i);
}
}
nums.add(newNumber);
}
public void print(){
String str = "";
Iterator it = nums.iterator();
if(it.hasNext()){
str += "num: [ " + (Integer) it.next();
}
while(it.hasNext()){
str += " , " + (Integer) it.next();
}
str += " ]";
System.out.println(str);
}
}
I would either use a circular array or a linked list for this. Depending on what you plan to use the list of numbers for.