I am trying to make a program that creates an ArrayList given the type as well as the values that will be put into the ArrayList. The input structure that we have to work with is "I 6 7 5 3 1 -1 2" with the I being the type Integer (or S for String, etc) and the first number (6) being how many values are in the ArrayList. I'm not sure how to instantiate the ArrayList.
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String type = scan.next();
int length = scan.nextInt();
int counter = 0;
if (type.equals("I")) {
ArrayList<Integer> A = new ArrayList<Integer>;
}
else if (type.equals("S")) {
ArrayList<String> A = new ArrayList<String>;
}
else if (type.equals("D")) {
ArrayList<Double> A = new ArrayList<Double>;
}
else {
System.out.println("Invalid type");
}
while (scan.hasNext() && counter<length) {
String s1 = scan.next();
A.add(s1);
counter += 1;
}
System.out.print(A);
}
//Removes any duplicate values in the arraylist by checking each value after it
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
ArrayList<E> inArray = list;
for (int i = 0; i<inArray.size(); i++) {
for (int j = i+1; j<inArray.size(); j++) {
if (inArray.get(i) == inArray.get(j)) {
inArray.remove(j);
}
}
}
return inArray;
}
//Shuffles the contents of the array
public static <E> void shuffle(ArrayList<E> list) {
E temp;
int index;
Random random = new Random();
for (int i = list.size()-1; i > 0; i--) {
index = random.nextInt(i + 1);
temp = list.get(index);
list.set(index, list.get(i));
list.set(i, temp);
}
System.out.print(list);
return;
}
//Returns the largest element in the given arraylist
public static <E extends Comparable<E>> E max(ArrayList<E> list) {
E max = Collections.max(list);
System.out.println(max);
return max;
}
I cannot in good conscious give you the answer you want, but rather I'll give you the answer you need.
DON'T DO THAT!
It serves no purpose at all. Datatype erasure at compile time of generics makes the ArrayList<Whatever> act equivalently to ArrayList<?> You cannot ascertain the generic type during runtime unless you type check the elements within the ArrayList
You might as well write this code, it'll give you the same exact results:
public static ArrayList<?> returnProper(String type) {
if(type.length() == 1 && "ISD".contains(type)) {
return new ArrayList();
} else {
System.out.println("Invalid type");
return null;
}
}
THUS, PLEASE DON'T DO THAT
Replace the second E with an "?" and then fix the method to return.
public static <T> ArrayList<?> returnProper(String type) {
if (type.equals("I")) {
return new ArrayList<Integer>();
} else if (type.equals("S")) {
return new ArrayList<String>();
} else if (type.equals("D")) {
return new ArrayList<Double>();
} else {
System.out.println("Invalid type");
}
return null;
}
I have a working word occurrence program that took me a while to code (still new at Java) and I was wondering if I could get a little assistance. Here is my code that I have so far:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class TestWordOccurenceProgram {
public static void main(String[] args) {
String thisLine = null;
try {
FileReader fr = new FileReader("myTextDocument.txt");
BufferedReader br = new BufferedReader(fr);
//List<String> wordList = new ArrayList<>();
List<String> words = new ArrayList<>();
// make ArrayList of integers
List<Integer> counts = new ArrayList<>();
String word = "";
while ((thisLine = br.readLine()) != null ) {
word = word.concat(thisLine);
word = word.concat(" ");
}
String[] wordList = word.split("\\s");
for (int i = 0; i < wordList.length; i++) {
String temp = wordList[i];
if(words.contains(temp)) {
int x = words.indexOf(temp);
int value = counts.get(x);
value++;
counts.set(x, value);
}
else {
words.add(temp);
counts.add(1);
}
}
for (int i = 0; i < words.size(); i++) {
System.out.println(words.get(i) + ": " + counts.get(i));
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
Here is what "myTextDocument.txt" has:
i am a rabbit
a happy rabbit am
yay i am a rabbit
a rabbit i am yay
Here is my output:
i: 3
am: 4
a: 4
rabbit: 4
happy: 1
yay: 2
Does anyone know if I could arrange these items from the highest number of word occurrences to the lowest number of word occurrences? Any help would be great!
You can use Map instead of List. and use compare method to sort map via its value.
refer this code :
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class PQ {
public static void main(String[] args) {
String thisLine = null;
try {
FileReader fr = new FileReader("D:\\test.txt");
BufferedReader br = new BufferedReader(fr);
HashMap<String,Integer> map = new HashMap<String,Integer>();
ValueComparator comparator = new ValueComparator(map);
TreeMap<String, Integer> treemap = new TreeMap<String, Integer>(comparator);
while((thisLine = br.readLine()) != null){
String[] str = thisLine.split("\\s+");
for(String s:str){
if(map.containsKey(s)){
Integer i = map.get(s);
i++;
map.put(s,i);
}else{
map.put(s, 1);
}
}
}
treemap.putAll(map);
System.out.println(treemap);
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}
class ValueComparator implements Comparator<String>{
Map<String, Integer> base;
public ValueComparator(Map<String, Integer> base) {
this.base = base;
}
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return -1;
} else {
return 1;
}
}
}
Rather than using two separate lists (one with words, one with counts), why not create a WordAndCount object that has something like getWord and getCount methods? This WordAndCount class can implement Comparable, where you do comparisons based on count. Then, you can store a single List<WordAndCount>, and just sort the single list using Collections.sort.
Roughly, the outline could look like this:
public class WordAndCount implements Comparable<WordAndCount> {
private String word;
private int count;
public WordAndCount(String word) {...}
public void incrementCount() {...}
public int compareTo(WordAndCount other) {...}
}
Wrapping up the combination into a single class makes this much easier to solve, as it provides the easy link between word and its count.
I would recommend using Collections in Java for this, but instead you can use temp variables.
So the idea is to sort by counts. Pseudo-code before outputting:
int tempCount;
String tempWord;
for (int i = 1; i < counts.size(); i++) {
if (counts.get(i) < counts.get(i-1)) {
tempCount = counts.get(i-1);
tempWord = words.get(i-1);
counts.set(i-1, i);
counts.set(i, tempCount);
words.set(i-1, i);
words.set(i, tempWord);
}
You'd need an extra loop around that to correctly order them but hopefully gives you the right idea.
My code is:
public class Main{
public static void main(String[] args){
WordGroup wordgroupOne= new WordGroup ("You can discover more about a person in an hour of play than in a year of conversation");
WordGroup wordgroupTwo= new WordGroup ( "When you play play hard when you work dont play at all");
String[] quoteOne = wordgroupOne.getWordArray();
String[] quoteTwo = wordgroupTwo.getWordArray();
for (String words : quoteOne){
System.out.println(words);
}
for (String words : quoteTwo){
System.out.println(words);
}
}
}
WordGroup class:
import java.util.HashSet;
import java.util.HashMap;
public class WordGroup {
public String words;
public WordGroup (String getWords){
words = getWords.toLowerCase();
}
public String[] getWordArray(){
return words.split(" ");
}
public HashSet<String> getWordSet(){
HashSet<String> set = new HashSet<String>();
String[] p = getWordArray();
for (String items : p){
set.add(items);
}
System.out.println(set);
return set;
}
public HashMap<String, Integer> getWordCounts() {
HashMap<String, Integer> map = new HashMap<String, Integer>();
String[] q = getWordArray();
for (String stuff : q) {
Integer oldVal = map.get(stuff);
if (oldVal == null){
oldVal = 0;
}
map.put(stuff, oldVal+1);
}
System.out.println(map);
return map;
}
}
What I am trying to do is use the getWordSet() method using the two WordGroups and
iterate or loop over the HashSet returned and print the words from it.
Call getWordCounts() on the two WordGroups. Use keySet() to retrieve the set of keys. Loop over this set and print out the word and its count for both WordGroups.
Use the getWordSet() method to make complete set of all the words from both WordGroups.
Loop over the new HashSet to print a complete list of all words with the sum counts from each of the hashmaps.
I am struggling with all of these. Any help is much appreciated!!
If you want to create a combined list or set, you will have to merge the lists together and the maps together. I leave that exercise to you.
public static void main(String[] args)
{
WordGroup wg1 = new WordGroup(
"You can discover more about a person in an hour of play than in a year of conversation");
WordGroup wg2 = new WordGroup(
"When you play play hard when you work dont play at all");
wg1.processWord();
// iterate through all the distinct words
Set<String> dw1 = wg1.getDistinctWords();
for (String s : dw1)
{
System.out.println(s);
}
// use map entry to iterate through the entry set
Map<String, Integer> wc1 = wg1.getWordCounts();
for (Map.Entry<String, Integer> entry : wc1.entrySet())
{
if (entry != null)
{
// use stringbuilder to build a temp string
// instead of using +
StringBuilder sb = new StringBuilder();
sb.append(entry.getKey());
sb.append(": ");
sb.append(entry.getValue());
System.out.println(sb);
}
}
}
public class WordGroup
{
// as a class, made the results of the process private
private String originalWord;
// we declare generic versions of the Collections, instead of the specific
// implementation
private Set<String> distinctWords;
private Map<String, Integer> wordCounts;
public WordGroup(String s)
{
this.originalWord = s;
// here we declare and initialize the specific implementation
this.distinctWords = new HashSet<String>();
this.wordCounts = new HashMap<String, Integer>();
}
public void processWord()
{
List<String> toProcess = getWordList();
if (toProcess != null && !toProcess.isEmpty())
{
for (String s : toProcess)
{
// the set will automatically figure out if it should be in the
// set or not.
this.distinctWords.add(s);
// call the update or insert method
upsertString(s);
}
}
}
// this splits the string into a list
// you could probably use a utility class from guava or something to do this
// but i have coded a naive version
private List<String> getWordList()
{
List<String> splitList = new ArrayList<String>();
// check to see if there is anything there
if (this.originalWord != null && !this.originalWord.isEmpty())
{
String lowered = this.originalWord.toLowerCase();
String[] splits = lowered.split(" ");
if (splits != null)
{
int iSize = splits.length;
if (iSize > 0)
{
// basically create a string
for (int i = 0; i < iSize; i++)
{
splitList.add(splits[i]);
}
}
}
}
return splitList;
}
// helper method to see if we need to add to the count
private void upsertString(String s)
{
if (s != null && !s.isEmpty())
{
if (this.wordCounts != null)
{
// default to 1, if its an insert
Integer newCount = 1;
// if it already exists we want to update
if (this.wordCounts.containsKey(s))
{
Integer currentCount = this.wordCounts.get(s);
if (currentCount != null)
{
// update the count by 1
newCount += currentCount;
}
}
// insert the new item
// or overwrite, because it is the same key to the new count
this.wordCounts.put(s, newCount);
}
}
}
public String getOriginalWord()
{
return this.originalWord;
}
public void setOriginalWord(String originalWord)
{
this.originalWord = originalWord;
}
public Set<String> getDistinctWords()
{
return this.distinctWords;
}
public void setDistinctWords(Set<String> distinctWords)
{
this.distinctWords = distinctWords;
}
public Map<String, Integer> getWordCounts()
{
return this.wordCounts;
}
public void setWordCounts(Map<String, Integer> wordCounts)
{
this.wordCounts = wordCounts;
}
}
I have a TreeMap in which I have stored some values. The map is sorted using the values, from highest to lowest. Now I want print out the contents of the TreeMap with their various indices.
If I have the following pairs in the map :
("Andrew", 10),
("John", 5),
("Don",9),
("Rolex", 30),
("Jack", 10),
("Dan",9)
I want to print out:
Rolex, 30 , 1
Jack, 10, 2
Andrew, 10, 2
Dan, 9, 4
Don, 9, 4
John, 5, 6.
This is what I've been trying but it doesn't seem to work well:
/**
*
* #author Andrew
*/
import java.util.*;
public class SortArray {
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>>entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
#Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res!= 0 ? res : 1;
//return e1.getValue().compareTo(e2.getValue());
}
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
public void test(){
Map mm = new TreeMap();
mm.put("Andrew", 11);
mm.put("Mbata", 21);
mm.put("Chinedu", 14);
mm.put("Bol", 14);
mm.put("Don", 51);
mm.put("Rolex", 16);
mm.put("Son", 41);
SortedSet newMap = entriesSortedByValues(mm);
Iterator iter = newMap.iterator();
int x = newMap.size();
List names = new ArrayList();
List scores = new ArrayList();
while(iter.hasNext()){
String details = iter.next().toString();
StringTokenizer st = new StringTokenizer(details, "=");
String name = st.nextToken();
names.add(name);
String score = st.nextToken();
scores.add(score);
//System.out.println(name + " Score:" +score + " Position:" + x);
x--;
}
Collections.reverse(names);
Collections.reverse(scores);
int pos = 1;
for(int i = 0; i<names.size();){
try{
int y = i+1;
if(scores.get(i).equals(scores.get(y))){
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
System.out.println("Position: "+ String.valueOf(pos));
//pos++;
i++;
continue;
} else{
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
System.out.println("Position: "+ String.valueOf(pos++));
}
i++;
} catch(IndexOutOfBoundsException e) {}
}
}
public SortArray(){
test();
}
public static void main(String [] args){
new SortArray();
}
}
First of all, Why are you catching that IndexOutOfBoundsException and doing nothing with it? if you run that you'll get that exception thrown (and I thing you already know it) the problem is in your algorithm inside the last "for" loop. I shouldn't give you the solution, but wth... at least you did some effort to make it run, so this is a more less working version:
import java.util.*;
public class SortArray {
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>>entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
#Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1;
//return e1.getValue().compareTo(e2.getValue());
}
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
public void test(){
Map mm = new TreeMap();
mm.put("Andrew", 11);
mm.put("Mbata", 21);
mm.put("Chinedu", 14);
mm.put("Bol", 14);
mm.put("Don", 51);
mm.put("Rolex", 16);
mm.put("Son", 41);
SortedSet newMap = entriesSortedByValues(mm);
Iterator iter = newMap.iterator();
int x = newMap.size();
List names = new ArrayList();
List scores = new ArrayList();
while(iter.hasNext()){
String details = iter.next().toString();
StringTokenizer st = new StringTokenizer(details, "=");
String name = st.nextToken();
names.add(name);
String score = st.nextToken();
scores.add(score);
//System.out.println(name + " Score:" +score + " Position:" + x);
x--;
}
Collections.reverse(names);
Collections.reverse(scores);
int pos;
int posBis = 0;
String lastScore = "";
for(int i = 0; i<names.size(); i++){
System.out.print("Name: "+ names.get(i)+"\t");
System.out.print("Score: "+ scores.get(i)+"\t");
if(i == 0 || !lastScore.equals(scores.get(i))) {
pos = i + 1;
posBis = pos;
} else {
pos = posBis;
}
System.out.println("Position: "+ String.valueOf(pos));
lastScore = (String)scores.get(i);
}
}
public SortArray(){
test();
}
public static void main(String [] args){
new SortArray();
}
}
Your SortedSet is the wrong way to go about this. You can see in your Comparator that it gets a bit messy when both values have to be looked up by the same key then you've got this messy (and incorrect) return res != 0 ? res : 1 (the 1 should really be e1.getKey().compareTo(e2.getKey()) rather than always returning 1).
A better way to go about this would be to just sort the keys yourself in a List, rather than creating a separate SortedSet. This way you don't have to worry about duplicate sorting values.
You can also abstract out the Comparator stuff a little, to make it more reusable in other code later, if you need it.
import java.util.*;
public class PrintSomething {
public static <T extends Comparable<T>> Comparator<T> reverseComparator(final Comparator<T> oldComparator) {
return new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
return oldComparator.compare(o2, o1);
}
};
}
public static <K,V extends Comparable<V>> Comparator<K> keyedComparator(final Map<K,V> lookup) {
return new Comparator<K>() {
#Override
public int compare(K o1, K o2) {
return lookup.get(o1).compareTo(lookup.get(o2));
}
};
}
public static void main(String[] args) {
Map<String, Integer> mm = new HashMap<>();
mm.put("Andrew", 10);
mm.put("John", 5);
mm.put("Don", 9);
mm.put("Rolex", 30);
mm.put("Jack", 10);
mm.put("Dan", 9);
Comparator<String> comparator = reverseComparator(keyedComparator(mm));
List<String> keys = Arrays.asList(mm.keySet().toArray(new String[mm.size()]));
//Collections.sort(keys); // optional, if you want the names to be alphabetical
Collections.sort(keys, comparator);
int rank = 1, count = 0;
Integer lastVal = null;
for (String key : keys) {
if (mm.get(key).equals(lastVal)) {
count++;
} else {
rank += count;
count = 1;
}
lastVal = mm.get(key);
System.out.println(key + ", " + mm.get(key) + ", " + rank);
}
}
}
In general things like SortedSet make more sense when you need to keep the data itself sorted. When you just need to process something in a sorted manner one time they're usually more trouble than they're worth. (Also: is there any reason why you're using a TreeMap? TreeMaps sort their keys, but not by value, so in this case you're not taking advantage of that sorting. Using a HashMap is more common in that case.)
You do a lot of work with the iterator, calling toString(), then splitting the results. And your Comparator is extra work too. Stay with a Map on both sides - you can use keys() and values() more directly, and let Java do the sorting for you. Most of your above code can be replaced with: (for clarity, I changed your name "mm" to "originalMap")
Map<Integer, String> inverseMap = new TreeMap<Integer, String>();
for (Map.Entry<String, Integer> entry : originalMap.entrySet()) {
inverseMap.put(entry.getValue(), entry.getKey());
}
Now, iterate over inverseMap to print the results. Note that if a count does exist twice in originalMap, only one will be printed, which is what you want. But which one gets printed left as an exercise for the reader :-). You might want to be more specific on that.
EDIT ADDED: If you do want to print out duplicate scores, this is not what you want. The original post I read said to skip if they were the same, but I don't see that after the edits, so I'm not sure if this is what OP wants.
I seem to be having some problems witn my quicksort method. I am trying to sort an ArrayList of objects using my quicksort method. I am using the Apache POI library to extract data from an excel file and I am adding this data to my arraylist. I have confirmed that my arraylist is not empty by printing out the arraylist before applying the quicksort method.
My problem seems to be that after passing in my arraylist of objects it gets reset to null and the size of the arraylist becomes 0. I got a java IndexOutOfBounds Exception within my quicksort method while trying get an object from the arraylist. Any help would be appreciated, thanks !
Here is my main class :
EDIT I solved my problem using the given solution below, but I still don't understand why my quicksort function doesn't work. I would appreciate it if someone could look at the quicksort function and tell me where I am going wrong. Thanks !
public class Test {
private static ArrayList<Object> incom = new ArrayList<Object>();
private static int period;
private static String termination = "yes";
private static int pivotVal;
private static ArrayList<String> treatment_name = new ArrayList();
private static ArrayList<Integer> treatment_cstart = new ArrayList();
private static ArrayList<Integer> treatment_cend = new ArrayList();
private static ArrayList<Integer> treatment_cost = new ArrayList();
private static ArrayList<Integer> bridge_part = new ArrayList();
private static ArrayList<Integer> budget = new ArrayList();
private static Scanner input = new Scanner(System.in);
private static Scanner alt = new Scanner(System.in).useDelimiter("\n");
public static void main(String[] args)
{
processFile();
}
public static void processFile(){
try {
POIFSFileSystem fs =
new POIFSFileSystem(new FileInputStream("Book2.xls"));
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet =wb.getSheet("Table0");
RowProcessor ip = IncomeProcessor.getInstance();
Object [] incomes = ip.process(sheet);
for (int i=0; i<incomes.length; i++)
incom.add(incomes[i]);
for (int i=0; i<incom.size(); i++)
{
Income income = (Income)incom.get(i);
System.out.println(income.getBridgeID() + " " + income.getDeckState());
}
incom = quicksort(incom);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static ArrayList<Object> quicksort(ArrayList<Object> income){
int pivot = income.size()/2;
int samePivotVal = 0;
ArrayList<Object> greater = new ArrayList<Object>();
ArrayList<Object> lesser = new ArrayList<Object>();
Income pivotIncome = (Income) income.get(pivot);
pivotVal = pivotIncome.getDeckState();
Income in;
for(int i=0; i<income.size() ;i++){
in = (Income)income.get(i);
if(in.getDeckState() > pivotVal)
greater.add(in);
else if(in.getDeckState() < pivotVal)
lesser.add(in);
else
samePivotVal++;
}
lesser = quicksort(lesser);
for(int i=0; i<samePivotVal; i++)
lesser.add(pivotIncome);
greater = quicksort(greater);
ArrayList<Object> sorted = new ArrayList<Object>();
for(Object result : lesser)
sorted.add(result);
for(Object result : greater)
sorted.add(result);
return sorted;
}
}
It will be a lot easier (and better) if you use Java's builtin sorting methods.
public static void processFile(){
//...
Collections.sort(incom, new IncomComparator());
//...
}
class IncomComparator implements Comparator<Object> {
#Override
public int compare(Object o1, Object o2) {
/* compare logic goes here
return a negative number when o1 < o2
a positive number when o1 > o2
0 when o1 == o2
*/
return 0;
}
}
or in a more simple way
public static void processFile(){
//...
Collections.sort(incom, new Comparator<Object>() {
#Override
public int compare(Object o1, Object o2) {
/* compare logic goes here
return a negative number when o1 < o2
a positive number when o1 > o2
0 when o1 == o2
*/
return 0;
}
});
//...
}
You can see some more examples here.