program on arraylist java - java

System.out.println("Enter the appointment ID to see the full details :");
int y=in.nextInt();
int r;
for(r=0;r<count;r++)
{
if(all.get(r).getID()==y)
{
all.get(r).display();
}
}
I am using this code to retrieve the full details that have been entered using the get statement and display function. This is a small part of my program. I was wondering is there any other way to do it

A better way would be to use a HashMap<Integer,DetailsClass> instead of an ArrayList.
Then, instead of a loop, you'll just write :
HashMap<Integer,DetailsClass> map = new HashMap<>();
...
if (map.containsKey(y)) {
DetailsClass details = map.get(y);
details.display();
}
This makes the code simpler and more efficient, since searching for a key in a HashMap takes expected constant time, while searching the List takes linear time.
If you must use an ArrayList, at least leave the loop once you find the object you were looking for :
int y=in.nextInt();
for(int r=0;r<count;r++)
{
if(all.get(r).getID()==y)
{
all.get(r).display();
return; // or break; depending on where this for loop is located
}
}

Never loop over a List by index. You don't know what the internal implementation of the List is and looping might result on O(n^2) complexity.
I would suggest the following:
System.out.println("Enter the appointment ID to see the full details :");
final int y = in.nextInt();
for(final Thing thing : all) {
if(thing.getID() == y) {
thing.display();
}
}
Or, if you can use Java 8, then:
all.stream()
.filter(t -> t.getID() == y)
.findFirst()
.ifPresent(Thing::display);

Related

ArrayList to Stream in Java by grouping

I would like to get the highest score group by Id .If two highest score's are same then i would like get the highest score based on lowest Optional ID.I would like to get it in Java Stream.So far this code works.Is there any efficient way to rewrite this code in java stream
Example :
records=record.Person(batchNumber);
List<Person> highestRecords = new ArrayList<>();for(
Person s:records)
{
if(!highestRecords.isEmpty()) {
boolean contains = false;
for(Person ns: new ArrayList<>(highestRecords)) {
if(s.Id().compareTo(ns.Id()) == 0) {
contains = true;
if(s.getScore.compareTo(ns.getScore()) > 0
&& s.optionalId().compareTo(ns.optionalId()) < 0) {
highestRecords.remove(ns);
highestRecords.add(s)
}
}
}
if(contains == false) {
highestRecords.add(s);
}
}else {
highestRecords.add(s);
}
}
}
Don't convert this to a stream.
There is no one pure operation happening here. There are several.
Of note is the initial operation:
if(getNewPendingMatches.size() > 0)
That's always going to be false on the first iteration and you're always going to add one element in.
On subsequent iterations, life gets weird because now you're trying to remove elements while iterating over them. A stream cannot delete values from itself while iterating over itself; it only ever processes in one direction.
As written this code should not be converted to a stream. You won't gain any benefits in doing so, and you're going to actively harm readability if you do.

check unrepeated random number

I have a method that return a number:
public String getNum()
{
Random random = new Random();
return random.nextInt(1000) + "";
}
And I have this method that stores an object
public void store(User user)
{
String str = getNum();
user.setIdCode(str);
for (User users: userList)
{
if(users.getId() == user.getId())
{
user.setIdCode(getNum);
}
}
}
if Id is excited than re-set the id. This is for sure checks if the id exists the first time but how about the second time that id is set. there would be a possibility of repeating the same number. At the same time we cant go in infinite loop.
What you can try is add a few random numbers in a Set and then use them separately whenever you want.
What I mean by it is that if you're trying to get a random number every time, you can just store some random numbers at once and then retrieve them one by one when you need them.
In code, put this in some method called storeRandomNumbers() and call it in the beginning of your program. Also, declare the Set as a global variable.
You can also make a separate variable to keep track of how many random numbers have been used up and use it to retrieve the next random number from the Set.
The code would look something like this (makes changes according to your needs):
Random rand = new Random();
Set<Integer> uniqueRandoms = new HashSet<>();
while (uniqueRandoms.size()<10){
uniqueRandoms.add(rand.nextInt(11));
}
for (Integer i : uniqueRandoms){
// System.out.print(i+" ");
// retrieve them from here and use them whenever you want
}
Edit:
Yes as #Andreas gave the link to suggest, you don't compare Strings with ==, rather you use the equals() method.

Not able to generate a unique user-number

I have a problem when I'm trying to generate a unique customer-id in my application. I want the numbers to start from 1 and go up. I have a register-class using tree-map that generates the next customer-number using this code:
public String generateNumber()
{
int number = 1;
for(Map.Entry<String, Forsikringkunde> entry : this.entrySet())
{
if(entry.getValue().getNumber().equals(String.valueOf(number)))
{
number++;
}
}return String.valueOf(number);
}
When I generate customers in my application I get duplicates of the numbers even though I iterate through the map. When creating a customer I create the object, run this method, use a set-method for the ID and adds it to the register, but it doesn't work. Anyone have a solution?
If you're on Java 8, I suggest you try this:
int max = this.values()
.stream()
.map(Forsikringkunde::getNumber)
.mapToInt(Integer::parseInt)
.max()
.orElse(0);
return String.valueOf(max + 1);
Modify the code to instead find the maximum number in your map, and then use that+1:
public String generateNumber()
{
int max = -1;
for(Map.Entry<String, Forsikringkunde> entry : this.entrySet())
{
int entry = Integer.parseInt(entry.getValue().getNumber());
if(entry > max)
{
max = entry;
}
}
return String.valueOf(max + 1);
}
(This mimics your coding style. aioobe's answer shows how to do the same thing more elegantly.)
Your method doesn't work because the map is not iterated in order. For example, here's what happens if you iterate through two users with number 2 and 1 respectively:
Start with "number = 1"
Check if number == 2: it's not, so continue
Check if number == 1: it is, so set number = 2
Now the loop is done and number is 2, even though a user with id 2 already exists. If it had been iterated in order, it would have worked.

How shall I execute an ArrayList program with a loop that renders each index of the list one at a time?

How shall I execute a program where as long as the array/list [idk which one to use yet but I've been told that with ArrayList I don't have to predefine a size so I'll use that] it will keep looping and the values are observed or rendered one at a time?
I've tried using the while loop but basically all I got were errors asking for an array or saying incompatible types or something like that.
while (myList!=0) //Can I actually do this? Because I didn't define a data type for my list.
if myList(0).equals ("A") //problem here is that I need to go through every index of the list. I've tried to use a counter like if myList(counter).equals ("A") but it says its incompatible types?
{
//print something.
} else if myList(0).equals ("B")
{
//print something
}
I know the question is kinda confusing but the code [even if it's full of errors] is exactly what I want to do. I just don't know how to apply it. Any help, answers, links, articles, tutorials would be reaaaaly appreciated.
Looks like you're thinking of it in terms of a C pointer. The List always points to a List, never to a Node or anything like that. So you'd do something like this intsead:
for(String s : myList) {
if("A".equals(s)) {
} else if("B".equals(s)) {
}
}
If you're using an ArrayList or some other implementation of the List interface you aren't going to have direct access to the data using brackets or parentheses, meaning that saying something like myList[0] is meaningless. Instead, what you are going to want to do is use the get method and then compare it to whatever values you need. You will be able to get the length of your List by using the .size() method, so your code will look something like this
for(int i=0; i<myList.size(); i++)
{
if(myList.get(i).equals("A"))
{
//print something
}
else if(myList.get(i).equals("B"))
{
//print something else
}
else
{
//print something still different
}
}
The response that glowcoder gave is a more compact syntax for looping over ArrayLists and other Lists in Java and results in nicer code, but this is how you'd do it sans syntactic sugar.
Is this answer suitable for your question?
for (int i = 0; i < myList.length; i++) {
if ("A".equals(myList[i])) {
// print something.
} else if ("B".equals(myList[i])) {
// print something
}
}
This should be working and quite close to what you tried so far:
int counter = 0;
while(counter < myList.size()) {
if (myList.get(counter).equals("A") )
{
//print something.
} else if (myList.get(counter).equals("B"))
{
//print something
}
counter = counter + 1;
}
Note that this is not the preferred way of looping over a list, see glowcoder's answer for something more elegant.

How can I remove the while(true) from my loop in Java?

I've heard that using while(true) is a bad programming practice.
So, I've written the following code to get some numbers from a user (with default values). However, if the user happens to type in -1, then it will quit the program for them.
How should this be written then without a while(true)? I can think of a condition to make the while loop go off that will get caught right away without continuing on until the next iteration?
Here is how I have it now:
public static void main(String[] args)
{
System.out.println("QuickSelect!");
while (true)
{
System.out.println("Enter \"-1\" to quit.");
int arraySize = 10;
System.out.print("Enter the size of the array (10): ");
String line = input.nextLine();
if (line.matches("\\d+"))
{
arraySize = Integer.valueOf(line);
}
if (arraySize == -1) break;
int k = 1;
System.out.print("Enter the kth smallest element you desire (1): ");
line = input.nextLine();
if (line.matches("\\d+"))
{
k = Integer.valueOf(k);
}
if (k == -1) break;
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
}
while (true) is fine. Keep it.
If you had a more natural termination condition, I'd say to use it, but in this case, as the other answers prove, getting rid of while (true) makes the code harder to understand.
There is a Single Entry Single Exit (SESE) school of thought that suggests that you should not use break, continue or abuse exceptions to do the same for some value of abuse). I believe the idea here is not that you should use some auxiliary flag variable, but to clearly state the postcondition of the loop. This makes it tractable to formerly reason about the loop. Obviously use the stands-to-reason form of reasoning, so it is unpopular with the unwashed masses (such as myself).
public static void main(String[] args) {
...
do {
...
if (arraySize == -1) {
...
if (k != -1) {
...
}
}
} while (arraySze == -1 || k == -1);
...
}
Real code would be more complex and you would naturally(!) separate out the inputing, outputting and core "business" logic, which would make it easier to see what is going on.
bool exit = false;
while (!exit) {
...
...
if (k == -1) {
exit = true;
}
else {
List <Integer> ....;
quickselect(.......);
}
}
But as has been said before, your while loop is a valid usage in this situation. The other options would simply build upon the if statements to check for the boolean and exit.
While having a loop like this is not technically wrong, some people will argue that it is not as readable as the following:
bool complete = false;
while (!complete)
{
if (arraySize == -1)
{
complete = true;
break;
}
}
Additionally, it is sometimes a good idea to have a safety loop counter that checks to make sure the loop has not gone through, say, 100 million iterations, or some number much larger than you would expect for the loop body. This is a secure way of making sure bugs don't cause your program to 'hang'. Instead, you can give the user a friendly "We're sorry but you've discovered a bug.. program will now quit.." where you set 'complete' to true and you end the program or do additional error handling. I've seen this in production code, and may or may not be something you would use.
while ( true ) is perfectly fine here, since the condition is really "while the user doesn't want to quit"!
Alternatively you could prompt for both the inputs on one line to simplify the logic, and use "q" for quit: this allows you to refactor the loop to "while ( !line.equals("q") )".
The problem is that you're doing an awful lot in that loop, rather than separating the functionality into simple methods.
If you want to stick to a procedural approach, you could move the reading of the array size and k into separate methods, and use the fact that the result of an assignment is the assigned value:
for (int arraySize; ( arraySize = readArraySize ( input ) ) != -1;) {
final int k = readKthSmallestElement ( input );
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
However that's still a bit ugly, and not well encapsulated. So instead of having the two != -1 tests on separate variables, encapsulate arraySize, k and randomData in an object, and create a method which reads the data from the input, and returns either a QuickSelect object or null if the user quits:
for ( QuickSelect select; ( select = readQuickSelect ( input ) ) != null; ) {
select.generateRandomData();
select.quickSelect();
}
You might even want to go to the next stage of creating a sequence of QuickSelect objects from the input, each of which encapsulate the data for one iteration:
for ( QuickSelect select : new QuickSelectReader ( input ) ) {
select.generateRandomData();
select.quickSelect();
}
where QuickSelectReader implements Iterable and the iterator has the logic to create a QuickSelect object which encapsulates arraySize, k, the list and the quick select operation. But that ends up being quite a lot more code than the procedural variants.
I'd only do that if I wanted to reuse it somewhere else; it's not worth the effort just to make main() pretty.
Also note that "-1" doesn't match the regex "\\d+", so you really do have an infinite loop.
If you really don't like while(true) you can always go for for(;;). I prefer the latter because it seems less redundant.

Categories

Resources