I'm working on a project that creates a virtual database for films. I have two classes: MovieEntry (for the individual movie entry) and MovieDatabase (the larger class that contains the database and allows for additions, etc.) I'm getting a few errors, the first of them being that in the searchTitle method it says that Database is of an incompatible type. Can anyone tell me how to do these for-each loops? I read the book and I thought the ArrayList was supposed to go there but apparently not.
**import java.util.ArrayList;
import java.util.Scanner;
import java.io.*;
public class MovieDatabase
{
private ArrayList<MovieEntry> Database = new ArrayList<MovieEntry>();
public MovieDatabase(){
ArrayList<MovieDatabase> Database = new ArrayList<MovieDatabase>(0);
}
public int countTitles() throws IOException{
Scanner fileScan;
fileScan = new Scanner (new File("movies.txt"));
int count = 0;
String movieCount;
while(fileScan.hasNext()){
movieCount = fileScan.nextLine();
count++;
}
return count;
}
public void addMovie(MovieEntry m){
Database.add(m);
}
public ArrayList<MovieEntry> searchTitle(String substring){
for (String title : Database)
System.out.println(title);
return null;
}
public ArrayList<MovieEntry> searchGenre(String substring){
for (String genre : Database)
System.out.println(genre);
return null;
}
public ArrayList<MovieEntry> searchDirector (String str){
for (String director : Database)
System.out.println(director);
return null;
}
public ArrayList<MovieEntry> searchYear (int yr){
ArrayList <String> yearMatches = new ArrayList<String>();
for (String s : Database)
s.getYear();
if(yearMatches.contains(y) == false){
yearMatches.add(y);
}
return yearMatches;
}
public ArrayList<MovieEntry> searchYear(int from, int to){
ArrayList <String> Matches = new ArrayList<String>();
for(Student s : movies);
Matches.add();
return Matches;
}
public void readMovieData(String movies){
String info;
try{
Scanner fileReader = new Scanner(new File(movies));
Scanner lineReader;
while(fileReader.hasNext()){
info = fileReader.nextLine();
lineReader = new Scanner(info);
lineReader.useDelimiter(":");
String title = lineReader.next();
String director = lineReader.next();
String genre = lineReader.next();
int year = lineReader.nextInt();
}
}catch(FileNotFoundException error){
System.out.println("File not found.");
}catch(IOException error){
System.out.println("Oops! Something went wrong.");
}
}
public int countGenres(){
String g;
ArrayList <String> gList = new ArrayList<String>();
for(Student s : movies){
String g = s.getGenre();
if(gList.contains(g) == false){
gList.add(g);
}
return gList.size();
}
}
public int countDirectors(){
ArrayList <String> dList = new ArrayList<String>();
for(Student s : movies){
String d = s.getDirector();
if(dList.contains(d) == false){
dList.add(d);
}
return dList.size();
}
}
public String listGenres(){
ArrayList <String> genreList = new ArrayList<String>();
}
}**
The type of the foreach variable (String, in the case of the loop in your searchTitle method) must be compatible with the type parameter (MovieEntry) of the parameterized type (ArrayList<MovieEntry>). This is clearly not the case. The following foreach loop would work:
for (MovieEntry title : Database) {
System.out.println(title);
}
Please consider following the convention of using lowercase names for fields, i.e. call your ArrayList<MovieEntry> with a name such as database instead of Database.
Well
for (Type obj : Collection) {...}
works only if the collection holds elements of type Type. This practically in your case means:
for (MovieDatabase database : Database) {...}
will work because Database is ArrayList holding the type MovieDatabase:
ArrayList<MovieDatabase> Database= new ArrayList<MovieDatabase>();
if you want to loop over titles in database you have to provide a method that gives back the list of Strings of titles, for example
public ArrayList<String> getTitles() {...}
....
for (String title : Database.getTitles()) {...}
Your Database property (should be database, lowercase), is of type:
ArrayList<MovieDatabase>
And you're trying to iterate over it using a String as the element type.
Your foreach should be:
for(MovieDatabase element: Database){
....
}
your for-each loop should look something like this (this is just an example so you'll have to adapt it for yours)
ArrayList<MovieEntry> list = new ArrayList<MovieEntry>();
...
for(MovieEntry m : list) {
...
}
an ArrayList is a valid thing to loop over but in your case you are trying to get Strings when your list doesn't hold Strings then you are calling methods on those Strings that String doesn't support. You have to use the right type for each list.
change
private ArrayList<MovieEntry> Database = new ArrayList<MovieEntry>();
public MovieDatabase(){
ArrayList<MovieDatabase> Database = new ArrayList<MovieDatabase>(0);
}
to
private ArrayList<MovieEntry> Database;;
public MovieDatabase(){
Database = new ArrayList<MovieDatabase>(0);
}
Related
I have a data Set like this:
1,JOHN,1934
2,TERENCE,1914
3,JOHN,1964
4,JOHN,1904
5,JOHN,1924
6,JOHN,1954
7,JOHN,1944
8,JOHN,1984
9,JOHN,1974
10,JOHN,1994
Which I've loaded in ArrayList of String[] from Text file like this:
ArrayList<String[]> records = new ArrayList<>();
String fileLocation = System.getProperty("user.dir");
String dataPath = fileLocation + File.separator + "boys-names.txt";
try {
try (BufferedReader br = new BufferedReader(new FileReader(dataPath))) {
String line;
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
records.add(values);
}
}
} catch (IOException e) {
e.printStackTrace();
}
I wanted to sort data set in increasing year like this:
4,JOHN,1904
2,TERENCE,1914
5,JOHN,1924
1,JOHN,1934
7,JOHN,1944
6,JOHN,1954
3,JOHN,1964
9,JOHN,1974
8,JOHN,1984
10,JOHN,1994
Problem: The built-in sorting method Collections.sort(list); of ArrayList only works on single type of data. But, in my case I have string with multi-type (string-integer) and sorting should base in Integers. So, is there any way to solve this problem?
Consider defining a model class for your data - let's call it MyData :
public class MyData {
private long id;
private String name;
private Year year;
//getters setters constructor
}
If the last integer value represents a year, why not use java.time.Year directly?
And then you could sort this list using List::sort method and passing a comparator :
Comparator<MyData> comparator = Comparator.comparing(MyData::getYear);
myDataList.sort(comparator);
By using java-8 lambda expression, write custom Comparator that compares Integer values and use Integer.valueOf for converting String to Integer
List<String[]> list = new ArrayList<String[]>();
String[] ar1 = {"1","JOHN","1934"};
String[] ar2 = {"2","TERENCE","1914"};
list.add(ar1);
list.add(ar2);
list.sort((c1,c2)->Integer.valueOf(c1[2]).compareTo(Integer.valueOf(c2[2])));
list.forEach(i->System.out.println(Arrays.toString(i)));
Output
[2, TERENCE, 1914]
[1, JOHN, 1934]
This would work:
public static void main(String[] args) {
List<String[]> records = new ArrayList<>();
records.add(new String[] {"1", "John", "1934"});
records.add(new String[] {"2", "Terence", "1914"});
Collections.sort(
records,
(o1, o2) -> {
Integer year_o1 = Integer.parseInt(o1[2]);
Integer year_o2 = Integer.parseInt(o2[2]);
if (year_o1 < year_o2) {
return -1;
} else if (year_o1 > year_o2) {
return 1;
} else {
return 0;
}
});
}
I'm in the process of building a basic database using csv files, and i'm currently testing the select function out when i ran into something strange.
private ArrayList<Record> selectField(String selectTerm)
{
Log.log("Selection " + selectTerm,2,"DB_io");
ArrayList<Record> ret = new ArrayList<Record>();
if (titleRow.values.contains(selectTerm))
{
Log.log("Adding values to " + selectTerm);
int ordinal = titleRow.values.indexOf(selectTerm);
Log.log("Ordinal " + ordinal);
List<String> tempList = new ArrayList<String>();
for (Record r : data)
{
List<String> tempList = new ArrayList<String>();
tempList.add(r.values.get(ordinal));
Record s = new Record(tempList);
ret.add(s);
tempList.clear();
}
Log.log("Number of records in ret " + ret.size());
for (Record t : ret)
{
Log.log(t.toString());
}
}
else
{
Log.log("keyField does not contain that field");
return null;
}
Log.log("Values " + ret.toString());
return ret;
}
When i do this, the part where it logs t.ToString() shows the record to be empty, whereas if i log it before tempList.clear(), it shows the record to be containing data like it should.
If i move the tempList declaration into the Record r : data loop, then it works fine and the Record t : ret loop works outputs the contents of the record like it should
Why is this?
Edit : Record class
public class Record
{
List<String> values = new ArrayList<String>();
public Record(List<String> terms)
{
this.values = terms;
}
public Record(String[] s)
{
this.values = Arrays.asList(s);
}
public String toString()
{
return values.toString();
}
}
Your Record instance holds a reference to the ArrayList instance you passed to its constructor. Therefore, when you call tempList.clear(), you clear the same List that your Record instance is holding a reference to.
You shouldn't call tempList.clear(), since you are creating a new ArrayList in each iteration of your loop anyway.
you are referencing object from more than one place and clear method is cleaning object by setting its reference to null:
instead of ret.add(s); you can use ret.add(s.clone());
I've two classess CsvRead and MyOwnClass.
In CsvRead I've a method public static List getDataFromCsv(); It returns list of all data. And this data I want to take in another method in class MyOwnClass and return there as list of objects of My OwnClass
It looks like this:
List<String> dataFromCsv = new ArrayList<String>();
And in another class, I want to convert it to List<Object> of my class.
private static List<String> getDataFromCsvClass = new ArrayList<String>();
getDataFromCsvClass = CsvReader.getAllCsvData(filename);
String name = dataFromCsv[0];
String surname = dataFromCsv[1];
String birth = dataFromCsv[2];
I want to return new MyOwnClass(name, surname, birth);
MY ERROR: array required but List found: String name = allData[0]; etc
You can create a method to convert a String to MyOwnClass and use stream to map the elements, e.g.:
public static MyOwnClass convertToObject(String element){
String[] tokens = element.split(",");
return new MyOwnClass(tokens[0], tokens[1], tokens[2]);
}
//code to convert
List<String> dataFromCsv = new ArrayList<String>();
List<MyOwnClass> list = dataFromCsv.stream()
.map(e -> convertToObject(e))
.collect(Collectors.toList());
However, this may not work if let's say name or surname contains comma. In which case, I would recommend having a look at OpenCSV library and this example of how to read csv into objects.
Supposing that the list contains the name, surname and birth in every group of 3 strings (i.e., the elements on index 0, 3, 6, 9 etc. contain the name), you might try the following:
public List<MyOwnClass> convertCsvData(List<String> csv_data)
{
// Initialize result
List<MyOwnClass> result;
result = new ArrayList<MyOwnClass>();
// Parse data
int counter;
String name;
String surname;
String birth;
for (counter = 0; counter < csv_data.size(); counter += 3)
{
name = csv_data.get(counter);
surname = csv_data.get(counter + 1);
birth = csv_data.get(counter + 2);
result.add(new MyOwnClass(name, surname, birth));
}
// Done
return (result);
} // convertCsvData
Somthing like this :
private static MyOwnClass toMyOwnClass(String str){
String[] object= str.split(",");
return new MyOwnClass(object[0], object[1], object[2]);
}
List<String> dataFromCsv = new ArrayList<String>();
List<MyOwnClass> list = new ArrayList<>();
for(String string : dataFromCsv ){
if(StringUtils.isNoneEmpty(string)){
list.add(toMyOwnClass(string));
}
}
And then you return your list
This is my code:
ArrayList<String> contentArray = new ArrayList<String>();
for(HashMap<ArrayList<String>, String> subTopicsEntry : subTopics){
contentArray = (ArrayList<String>) subTopicsEntry.get("Content");
}
It gives me error that arraylist cannot be cast to java.lang.string.
What is wrong here?
If i do it like this:
ArrayList<?> contentArray = new ArrayList<?>();
for(HashMap<?, ?> subTopicsEntry : subTopics){
contentArray = (ArrayList<?>) subTopicsEntry.get("Content");
}
it works
What is the difference ?
First of all Arrays.asList() returns List<String>, not ArrayList<String>.
You have to define your variable as this:
List<String> contentArray = new ArrayList<String>();
But that's not all the problems you have here.
As commenters have noted, you have (probably) misdeclared your Map. Perhaps you mean
ArrayList<String> contentArray = new ArrayList<String>(); // this initializer is unnecessary, btw
for(HashMap<String, ArrayList<String>> subTopicsEntry : subTopics){
contentArray = subTopicsEntry.get("Content"); // Note that a cast is no longer necessary
}
I question whether you really want ArrayLists here, but without seeing the rest of your code it's hard to say.
My answer code is:
package Examples;
import java.util.ArrayList;
import java.util.List;
public class ExampleClass
{
private List<String> _list;
#Override
public String toString() // override default method
{
String temp = "";
for (String s : this._list)
{
temp += (temp.length() == 0 ? "" : ", ") + s;
}
return "ExampleClass: [" + temp + "]";
}
public ExampleClass() // initialize this example class
{
this._list = new ArrayList<>();
this._list.add("Hello!");
this._list.add("Ciao!");
this._list.add("Good morning!");
this._list.add("Good afternoon!");
}
}
/*
// some code for using example
ExampleClass ec = new ExampleClass();
// prints next text to console:
// ExampleClass: [Hello!, Ciao!, Good morning!, Good afternoon!]
System.out.println(ec.toString());
*/
Have a nice day. Yuri
public static void main(String[] args)
{
String input="jack=susan,kathy,bryan;david=stephen,jack;murphy=bruce,simon,mary";
String[][] family = new String[50][50];
//assign family and children to data by ;
StringTokenizer p = new StringTokenizer (input,";");
int no_of_family = input.replaceAll("[^;]","").length();
no_of_family++;
System.out.println("family= "+no_of_family);
String[] data = new String[no_of_family];
int i=0;
while(p.hasMoreTokens())
{
data[i] = p.nextToken();
i++;
}
for (int j=0;j<no_of_family;j++)
{
family[j][0] = data[j].split("=")[0];
//assign child to data by commas
StringTokenizer v = new StringTokenizer (data[j],",");
int no_of_child = data[j].replaceAll("[^,]","").length();
no_of_child++;
System.out.println("data from input = "+data[j]);
for (int k=1;k<=no_of_child;k++)
{
family[j][k]= data[j].split("=")[1].split(",");
System.out.println(family[j][k]);
}
}
}
i have a list of family in input string and i seperate into a family and i wanna do it in double array family[i][j].
my goal is:
family[0][0]=1st father's name
family[0][1]=1st child name
family[0][2]=2nd child name and so on...
family[0][0]=jack
family[0][1]=susan
family[0][2]=kathy
family[0][3]=bryan
family[1][0]=david
family[1][1]=stephen
family[1][2]=jack
family[2][0]=murphy
family[2][1]=bruce
family[2][2]=simon
family[2][3]=mary
but i got the error as title: in compatible types
found:java.lang.String[]
required:java.lang.String
family[j][k]= data[j].split("=")[1].split(",");
what can i do?i need help
nyone know how to use StringTokenizer for this input?
Trying to understand why you can't just use split for your nested operation as well.
For example, something like this should work just fine
for (int j=0;j<no_of_family;j++)
{
String[] familySplit = data[j].split("=");
family[j][0] = familySplit[0];
String[] childrenSplit = familySplit[1].split(",");
for (int k=0;k<childrenSplit.length;k++)
{
family[j][k+1]= childrenSplit[k];
}
}
You are trying to assign an array of strings to a string. Maybe this will make it more clear?
String[] array = data.split("=")[1].split(",");
Now, if you want the first element of that array you can then do:
family[j][k] = array[0];
I always avoid to use arrays directly. They are hard to manipulate versus dynamic list. I implemented the solution using a Map of parent to a list of childrens Map<String, List<String>> (read Map<Parent, List<Children>>).
public static void main(String[] args) {
String input = "jack=susan,kathy,bryan;david=stephen,jack;murphy=bruce,simon,mary";
Map<String, List<String>> parents = new Hashtable<String, List<String>>();
for ( String family : input.split(";")) {
final String parent = family.split("=")[0];
final String allChildrens = family.split("=")[1];
List<String> childrens = new Vector<String>();
for (String children : allChildrens.split(",")) {
childrens.add(children);
}
parents.put(parent, childrens);
}
System.out.println(parents);
}
The output is this:
{jack=[susan, kathy, bryan], murphy=[bruce, simon, mary], david=[stephen, jack]}
With this method you can directory access to a parent using the map:
System.out.println(parents.get("jack"));
and this output:
[susan, kathy, bryan]