Trying to link objects in 2 seperate Array Lists - java

Thank you for taking the time to look at this. I am having some trouble with a project of mine. As of now I have 2 array lists that collect names and ids. I want to link the objects of both lists (the name and id) with each other so that I can perform a insertion sort algorithm later.
Tasks:
1) Ask the user to input names and IDs for team members. Users should alternate inputting names and IDs on separate lines, as shown in the sample run below. As the information is provided, TeamMembers will be added to an ArrayList of TeamMember objects. Remember that names should be stored in title case inside of the TeamMember class.
2)The user should enter the word "STOP" in any combination of lowercase and uppercase letters to stop entering team member information.
3)Sort the ArrayList in increasing order by ID using the insertion sort algorithm. You can choose to use the insertion sort algorithm as you are inserting each new TeamMember object into the array, or you can wait until the entire array is constructed before sorting all of its members at once.
4)After all the names are entered and sorted, print the contents of the ArrayList using ArrayList.toString().
package com.company;
import java.util.*;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
String inputName;
String inputID;
List<String> fullName = new ArrayList<String>();
List<String> idString = new ArrayList<String>();
while (!(fullName.contains("stop"))) {
Scanner uInput = new Scanner(System.in);
//String checkInput = "test";
System.out.println("Please enter the name: ");
inputName = uInput.nextLine();
fullName.add(inputName.toLowerCase());
// System.out.println("List: " + fullName); //Check what is in the fullName List
// System.out.println("List Size: " + fullName.size()); // Check the size of fullName ArrayList
System.out.println("Please enter the ID: ");
inputID = uInput.nextLine();
idString.add(inputID.toLowerCase());
}
fullName.remove(fullName.size() - 1); //removing the last word, which is always "stop"
idString.remove(idString.size() - 1); //(Same as above)
//insertionSort(fullName);
//insertionSort(idString);
}
HashMap newmap = new HashMap(); //creating hash map
Best, Nate

As the information is provided, TeamMembers will be added to an ArrayList of TeamMember objects
So, you need to have a TeamMember class that has the names and ids
class TeamMember {
private String name;
private String id;
public TeamMember(String name, String id) {
this.name = name;
this.id = id;
}
}
Remember that names should be stored in title case inside of the TeamMember class.
Refer to this post for converting a String to title case
Clues for rest of your work:
The user should enter the word "STOP" in any combination of lowercase and uppercase letters to stop entering team member information.
After getting the name, use String's equalsIgnoreCase to check if the entered String is a variation of STOP.
Sort the ArrayList in increasing order by ID using the insertion sort algorithm.
Either you must pass a Comparator (to the sorting method) or make TeamMember implement Comparable to compare two TeamMember objects

Related

Pairing among the members in same list in java

In problem statement, I have 'n' number of families with 'n' number of family members.
eg:
John jane (family 1)
tiya (family 2)
Erika (family 3)
I have to assign all members in such a way that person should not pair with the his family member.
and output should be:
John => tiya
jane => Erika
tiya => jane
Erika => john
I have created the object Person(name ,familyID, isAllocated).
Created the list and added personName_id in this this.
I am thinking to use the map for association. So that john_1 will be key and tiya_2 will be value.
I am failing to associate those pairs through map. How can I shuffle the members it the list.
Also, It would be nice if anyone could suggest me the better solution.
Code:
Getting person:
public static List getperson()
{
Scanner keyboard = new Scanner(System.in);
String line = null;
int count = 0;
List <Person> people = new ArrayList<>();
while(!(line = keyboard.nextLine()).isEmpty()) {
String[] values = line.split("\\s+");
//System.out.print("entered: " + Arrays.toString(values) + "\n");
int familyid = count++;
for(String name :values)
{
Person person = new Person();
person.setFamilyId(familyid);
person.setName(name);
person.setAllocated(false);
people.add(person);
}
}
return people;
}
Mapping:
public static List mapGifts(List pesonList)
{
Map<String , String> personMap = new HashMap<String , String>();
Iterator<Person> itr = pesonList.iterator();
Iterator<Person> itr2 = pesonList.iterator();
List<String> sender = new ArrayList<>();
while(itr.hasNext())
{
Person p = itr.next();
sender.add(p.getName()+"_"+p.getFamilyId());
personMap.put(p.getName()+"_"+p.getFamilyId(), "");
// p.setAllocated(true);
}
while(itr2.hasNext())
{
/*if(p.isAllocated())
{*/
// Separate Sender name and id from sender list
//check this id match with new p1.getFamilyId()
for(String sendername :sender)
{
// System.out.println("Sender "+sendername);
personMap.put(sendername, "");
String[] names = sendername.split("_");
String part1 = names[0]; // 004
String familyId = names[1]; // 004
Person p2 = itr2.next();
System.out.println(p2.getFamilyId() +" "+familyId +" "+p2.isAllocated());
if(p2.isAllocated())
{
for ( String value: personMap.values()) {
if ( value != sendername) {
}
}
}
if( p2.getFamilyId() != Integer.parseInt(familyId))
{
// add values in map
}
}
break;
// Person newPerson = personLists.get(j);
}
for (Iterator it = personMap.entrySet().iterator(); it.hasNext();)
{
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println("Gifts "+key+"=>"+value);
}
return pesonList;
}
Thanks
From what I've read, you only care that you match people. How they match doesn't matter. That said, I'll assume you have a list of FamilyID's, and a list of names of everyone, and that you can sort the list of people according to family IDs.
Let's call them:
List<FamilyID> families; and
LinkedList<Person> people;, respectively. (You can make FamilyID an enumerated class)
We need two hashmaps. One to generate a list (essentially an adjacency list) of family members given a familyID:
HashMap<FamilyID, List<Person>> familyMembers; ,
and one to generate a list of sender(key) and receiver(value) pairs:
HashMap<Person, Person> pairs;
A useful function may be that, when given a person and their family ID, we can find the next available person who can receive from them.
String generateReceiver(Person newSender, FamilyID familyID);
Implementation of this method should be pretty straightforward. You can iterate through the list of people and check to see if the current person is not a family member. If that condition passes, you remove them from the "people" list so you don't try to iterate through them again. If you're using a linked list for this, removal is O(1) since you'll already have the reference. Worst case on traversals the list is n + n - 1 + ... + 2 times to get O(n^2) time efficiency (i.e. you have one large family and many small ones). Work around that would be to ditch the LinkedList, use an Array-based list, and keep a separate array of index values corresponding to each "currently available receiver of a specified family". You'd initialize these values as you added the people from each family to the people list (i.e. start of family 1 is index "0"; if family 1 has 2 people, start of family 2 would be index "2"). This would make the function O(1) time if you just incremented the current available receiver index everytime you added a sender-receiver pair. (Message me if you want more details on this!)
Last but not least, the loop is doing this for all people.
for (List<Person> family : familyMembers)
for (Person person : family)
{
// get the next available receiver who is not a family member
// add the family member and its receiver to "pairs" hash
}
Note that the above loop is pseudocode. If you're wondering if you would generate conflicting receiver/senders with this method, you won't. The list of people is essentially acting as a list of receivers. Whichever way you implement the people list, the generateReceiver(...)eliminates the chance that the algorithm would see a faulty-receiver. Per efficiency, if you do the array based implementation then you're at O(N) time for generating all pair values, where N is the total number of people. The program itself would be O(N) space as well.
Of course, this is all based on the assumption you have enough people to match for sender-receiver pairs. You'd need to add bells and whistles to check for special cases.
Hope this helps! Good luck!

Java split and add elements into corrsponding data type arraylists

My problem is when a user enters text it should have two elements to split when using .split() however with the items it splits how do I put them into different lists so that I can use integer based list to make calculations.
e.g.
a user enters "skyrim , 100" the 'skyrim' entry is a string however with the number (integer) '100' I want to split it removing the comma and add it to a ArrayList for calculations and with other inputs added.
game name(String) , hours(integers) <- template
skyrim , 100
oblivion , 25
GTA V , 50
so the listed items above are user input with 2 arguments separated by a comma, which will be split, then I need to add them to different arraylists.
Scanner input = new Scanner(System.in);
Arraylist<String> game = new Arraylist<>();
Arraylist<Integer> hours = new Arraylist<>();
Arraylist<Object> allGameData = new Arraylist<>();
String gameEntry = input.nextLine().split(" , ");
allGameData.add(gameEntry);
foreach(object items : allGameData) {
System.out.println(items);
}
so from here I should have:
skyrim , 100 , oblivion, 25, GTAV , 50
How do i put the game names into the game list and the numbers into the hours list?
Well for starters, the class you should be using is ArrayList with a capital L. So you need to change:
Arraylist<String> game = new Arraylist<>();
Arraylist<Integer> hours = new Arraylist<>();
Arraylist<Object> allGameData = new Arraylist<>();
to this:
ArrayList<String> game = new ArrayList<>();
ArrayList<Integer> hours = new ArrayList<>();
ArrayList<Object> allGameData = new ArrayList<>();
After we have them initialized correctly we add to the ArrayList with #.add so in your case you would add to the game and hours list like:
game.add("some game");
hours.add(10);
When you split your input with input.nextLine().split(" , "); we are expecting a String array to be returned. Currently you are trying to set this to just a String instead of a String array.
while (true){
System.out.println("Enter \"game , hours\" or \"Quit\"");
String line = input.nextLine();
if (line.equals("Quit")) break;
allGameData.add(line);
String[] parsedData = line.split(" , ");
game.add(parsedData[0]);
hours.add(Integer.parseInt(parsedData[1]));
}
You can use Integer.parseInt(). The code you submitted looks pseudo-codey, but this is something like what You're going for:
String gameEntry = input.nextLine();
allGameData.add(gameEntry);
String[] splitGameEntry = input.nextLine().split(" , ");
game.add(splitGameEntry[0]);
hours.add(Integer.parseInt(splitGameEntry[1]));
I don't know exactly what you're trying to accomplish with this code, but you may want to organize the game/hours into a class that holds both values. Your code would then look something like this:
public class GameInfo
{
private String name;
private int hours;
public GameInfo(String name, int hours)
{
this.name = name;
this.hours = hours;
}
[getters/setters]
#Override
public String toString()
{
return name + ": " + hours + " hours played!";
}
}
public class Main
{
public void doSomething()
{
Scanner input = new Scanner(System.in);
List<GameInfo> gameInfo = new ArrayList<>();
String[] gameEntry = input.nextLint().split(" , ");
gameInfo.add(new GameInfo(gameEntry[0], Integer.parseInt(gameEntry[1]));
for(GameInfo gameInfoPiece : gameInfo)
{
System.out.println(gameInfoPiece);
}
}
}
Using this approach, you would be able to add as much information into the GameInfo class as you want. For instance, if you wanted to change hours to expectedHoursToComplete and add actualHoursToComplete, you could easily do that.
You may find it easier if you rethink your approach. Rather than have 3 separate lists why not store it all in a single Map<String,Integer> where the key is the game name and the value is the number of hours.
Your code would look something like the following:
Scanner scan = new Scanner(System.in);
Map<String, Integer> gameHoursMap = new HashMap<>();
String currentValue = scan.nextLine();
// Loop until you meet some criteria to end such as typing q or quit
while(!currentValue.equalsIgnoreCase("q")){
// You would need to handle when the value of currentValue doesn't fit what you would normally be expecting before doing the rest
String[] vals = currentValue.split(",");
// Call trim method on the String incase there is any lingering whitespace
gameHoursMap.put(vals[0].trim(), Integer.valueOf(vals[1].trim()));
currentValue = scan.nextLine();
}
You would obviously need to write some error handling for when the input doesn't fit with what you're expecting but you get the gist.
UPDATE:
If you wanted to have more complicated info stored for each game you could wrap it up in a custom class GameInfo and then have a Map<String,GameInfo> where the key is the name and the value is the GameInfo. This would allow you to retrieve all of the game info for a game just based on the name.
public class GameInfo {
private String name;
private int hoursPlayed;
private int level;
// etc
}
You would then amend the while loop to create the GameInfo object instead of just putting a String and int into the Map
// Create the GameInfo object from the corresponding input supplied by the user
GameInfo game = new GameInfo(vals[0].trim(), Integer.valueOf(vals[1].trim()), Integer.valueOf(vals[2].trim()));
// Put it in the map with the name as the key
gameMap.put(game.getName(), game);

Format an arraylist

I have a file that I am storing into an ArrayList and I can't figure out how to format it so that certain Strings of text are stored in particular indexes. The first line will be the category, second line the question and 3rd the answer to trivia questions. I need to do this so that I can then randomly pick questions then check the answers for a trivia game. All I get so far is every word separated by a comma. From the professor,
"The input file contains questions and answers in different categories. For each category, the first line indicates the name of the category. This line will be followed by a number of pairs of lines. The first line of the pair is the question, and the second line is its corresponding answer.
A blank line separates the categories."
Here is my code so far:
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class TriviaGamePlayer {
/**
* #param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ArrayList<String> triviaQuestion = new ArrayList<String>();
Scanner infile = new Scanner(new File("trivia.txt"));
while(infile.hasNext()){
triviaQuestion.add(infile.next());
}
System.out.println(triviaQuestion);
}
}
From what I can see in the question so far, You would be best off creating your own TriviaQuestion Object which would look something like
public class TriviaQuestion
{
public String question;
public String answer;
public boolean asked;
public String category;
TriviaQuestion (String q, String a, String c)
{
question = q;
answer = a;
category = c;
}
}
Then you have a few options, but if you have this Object then everything becomes a bit easier. I would create a Map<String,List<TriviaQuestion>> where the key is your category.
Then when reading the file, also you should use infile.hasNextLine() and inFile.nextLine()
Read a line (first I assume would be the category)
Read next two lines (question and answer)
Create new instance `new TriviaQuestion( question, answer, category)'
Add this to the Array list
Repeat until blank
If next line is blank, add list to map and loop back to (1)
Like: (this is assuming well formed file)
String line = inFile.nextLine(); //first line
String category = line;
while(infile.hasNextLine())
{
line = inFile.nextLine();
if(line.isEmpty()) //blank line
category = inFile.nextLine();
else
{
String q = line;
String a = inFile.nextLine();
//do other stuff
}
}
Then to ask a question get the list for the category, choose a random question then set it to asked so it doesn't come up again
ArrayList<TriviaQuestion> questions = yourMap.get("Science");
Integer aRandomNumber = 23 //(create a random Number using list size)
TriviaQuestion questionToAsk = questions.get(aRandomNumber)
System.out.println(questionToAsk.question)
questionToAsk.asked = true
I would approach this problem by identifying what is needed. You have a list of categories (Strings). Within each category, there will be a list of question (String) and answer (String) pairs. From there we already see some "logical" ways to organize the data.
Questions - String
Answers - String
Question/Answer pairs - Write a class (for now, lets refer to it as QAPair) with two Strings as fields (one for the question, one for the answer)
List of Q/A pairs within a category - ArrayList
List of Categories, mapped to a list of Q/A pairs - Maybe a Map would do the trick. The type would be: Map>
From there you would start parsing the file; for the first line, or after a blank line is encountered, you know the String will give a category name. You can call containsKey() to check if the category name already exists; if it does fetch the ArrayList of Q/A Pairs for that category and keep adding to the list, otherwise initialize a new ArrayList and add it to the map for that category.
You could then read a pair of lines. For each pair of lines you read initialize a QAPair object, then add it to the ArrayList for the category they belong to.
Here's an example of using a Map:
Map<String, ArrayList<QAPair>> categories = new HashMap<String, ArrayList<QAPair>>();
if (!categories.containsKey("Math")) { // Check to see if a Math category exists
categories.put("Math", new ArrayList<QAPair>()); // If it doesn't, create it
}
QAPair question1 = new QAPair("2+2", "4");
// get() method returns the ArrayList for the "Math" category
// add() method adds the QAPair to the ArrayList for the "Math" category
categories.get("Math").add(question1);
To get the list of categories from a map and pick one:
// Convert to an array of Strings
String[] catArray = categories.toArray(new String[0]);
// Get the 10th category in the array
// Use catArray.length to find how many categories there are total
catArray[10];

Iterate through multiple array lists with same index

Im a beginner in Java. I have 3 ArrayLists and all of the ArrayLists contain data pertaining to a specific subject and hence have the same length. I want to iterate through the array and perform some operations as illustrated below:
public void example(){
ArrayList<Long> ID = new ArrayList<Long>;
ArrayList<Integer> AcNo = new ArrayList<Integer>;
ArrayList<Integer> Vnum = new ArrayList<Integer>;
//get ID and AcNo from user, compare it in the ArrayList, get the corresponding Vnum
// for the Vnum from previous step, compare it with the next Vnum and get corresponding ID and AcNo until some *condition* is satisfied.
}
How do I do this in Java? I saw examples of Iterator, but Im not sure about the correct method to do this! Please help.
If all three lists are of the same length, then iterate over them using for loop with indexes. Same indexes represents the same user in each of the three lists:
for (int i=0; i<ID.size(); i++) {
Long userId= ID.get(i);
Integer userAcNo= AcNo.get(i);
Integer userVnum= Vnum.get(i);
//if the next user exist, get the next user
if (i + 1 < ID.size()) {
Long nextUserId= ID.get(i+1);
Integer nextUserAcNo= AcNo.get(i+1);
Integer nextUserVnum= Vnum.get(i+1);
//now compare userVariables and nextUser variables
}
}
A better approach would be to have a single list of Subject objects or similar, so that each Subject contains all relevant data about itself.
class Subject {
private final long id;
private final int acNo;
private final int vnum;
/* Appropriate constructor and getters... */
}
You might also want to consider renaming the fields so that they are more descriptive.

How to sort an array of strings alphabetically by second word in Java

I have a little problem with an assignment I'm working on. Basically, I have a file, with Student ID's and their first name in the following format:
17987 Beth
17950 Clark
17936 Aaron
I put the contents of the file in an array, and I need it sorted by the name, not the ID. If I use Arrays.sort(myArray) it will sort it automatically by ID. I'm having a hard time understanding the Comparator, so if you could explain it step by step, it would be easier for me.
Thank you!
You need to provide a Comparator that will look at the Strings passed to it, and they must have an understanding of what they are looking for. You can do this in a few different ways, but, if you know for certain about the content of the strings, then you can split the Strings based on their space and compare the second value. Alternatively, you could use a regular expression to extract those details.
class SecondWordComparator implements Comparator<String>
{
#Override
public int compare(String s1, String s2)
{
String[] a1 = s1.split(" ");
String[] a2 = s2.split(" ");
// you should ensure that there are actually two elements here
return a1[1].compareTo(a2[1]);
}
}
Use TreeMap, the entries will be sorted by key.
E.g.:
SortedMap<String, Integer> srtdMap = new TreeMap<String, Integer>();
srtdMap.put("Beth", 17987);
srtdMap.put("Aaron", 17936 );
srtdMap.put("Clark", 17950);
//key set always returns the same order by name
for(String name : srtdMap.keySet())
{
int id = srtdMap.get(name);
System.out.println("name = " + name + ", ID is " + id);
}
What you can do is run a for loop that would rearrange all the contents of the Array into a final array. Two for loops would be required. The first for loop will go through the Array and the for loop inside the first will look for the first letter and add it to the final Array/Arraylist .
For a object-oriented approach I would parse the file into a new class, Student, and save those in an Array(List). The class could extend Comparable<Student> There, you can separate the int ID and the String name and have the compareTo(Student student) method return name.compareTo(otherStudent.name). Then you can call the sort method and it will sort it as wanted.
As such:
public class Student implements Comparable<Student> {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public int compareTo(Student student) {
return name.compareTo(student.name);
}
}

Categories